SDL_bool SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result) { int Amin, Amax, Bmin, Bmax; if (!A) { SDL_InvalidParamError("A"); return SDL_FALSE; } if (!B) { SDL_InvalidParamError("B"); return SDL_FALSE; } if (!result) { SDL_InvalidParamError("result"); return SDL_FALSE; } /* Special cases for empty rects */ if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) { result->w = 0; result->h = 0; return SDL_FALSE; } /* Horizontal intersection */ Amin = A->x; Amax = Amin + A->w; Bmin = B->x; Bmax = Bmin + B->w; if (Bmin > Amin) Amin = Bmin; result->x = Amin; if (Bmax < Amax) Amax = Bmax; result->w = Amax - Amin; /* Vertical intersection */ Amin = A->y; Amax = Amin + A->h; Bmin = B->y; Bmax = Bmin + B->h; if (Bmin > Amin) Amin = Bmin; result->y = Amin; if (Bmax < Amax) Amax = Bmax; result->h = Amax - Amin; return !SDL_RectEmpty(result); }
void SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result) { int Amin, Amax, Bmin, Bmax; if (!A || !B || !result) { return; } /* Special cases for empty Rects */ if (SDL_RectEmpty(A)) { if (SDL_RectEmpty(B)) { /* A and B empty */ return; } else { /* A empty, B not empty */ *result = *B; return; } } else { if (SDL_RectEmpty(B)) { /* A not empty, B empty */ *result = *A; return; } } /* Horizontal union */ Amin = A->x; Amax = Amin + A->w; Bmin = B->x; Bmax = Bmin + B->w; if (Bmin < Amin) Amin = Bmin; result->x = Amin; if (Bmax > Amax) Amax = Bmax; result->w = Amax - Amin; /* Vertical union */ Amin = A->y; Amax = Amin + A->h; Bmin = B->y; Bmax = Bmin + B->h; if (Bmin < Amin) Amin = Bmin; result->y = Amin; if (Bmax > Amax) Amax = Bmax; result->h = Amax - Amin; }
static int D3D_UpdateClipRect(SDL_Renderer * renderer) { const SDL_Rect *rect = &renderer->clip_rect; D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; RECT r; HRESULT result; if (!SDL_RectEmpty(rect)) { IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE); r.left = rect->x; r.top = rect->y; r.right = rect->w + rect->w; r.bottom = rect->y + rect->h; result = IDirect3DDevice9_SetScissorRect(data->device, &r); if (result != D3D_OK) { D3D_SetError("SetScissor()", result); return -1; } } else { IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE); } return 0; }
SDL_bool SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B) { int Amin, Amax, Bmin, Bmax; if (!A) { SDL_InvalidParamError("A"); return SDL_FALSE; } if (!B) { SDL_InvalidParamError("B"); return SDL_FALSE; } /* Special cases for empty rects */ if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) { return SDL_FALSE; } /* Horizontal intersection */ Amin = A->x; Amax = Amin + A->w; Bmin = B->x; Bmax = Bmin + B->w; if (Bmin > Amin) Amin = Bmin; if (Bmax < Amax) Amax = Bmax; if (Amax <= Amin) return SDL_FALSE; /* Vertical intersection */ Amin = A->y; Amax = Amin + A->h; Bmin = B->y; Bmax = Bmin + B->h; if (Bmin > Amin) Amin = Bmin; if (Bmax < Amax) Amax = Bmax; if (Amax <= Amin) return SDL_FALSE; return SDL_TRUE; }
Rectangle::Rectangle(SDL_Rect rect) { if (!SDL_RectEmpty(&rect)) { x = rect.x; y = rect.y; w = rect.w; h = rect.h; } }
/* * SDL.rectEmpty(rect) * * Arguments: * rect the rectangle * * Returns: * True if empty */ static int l_rectEmpty(lua_State *L) { SDL_Rect rect; videoGetRect(L, 1, &rect); return commonPush(L, "b", SDL_RectEmpty(&rect)); }
Tile* Tile_create(const int type, TextureCache* tc, const char* colorPrefix) { Tile* this = malloc(sizeof(Tile)); this->type = type; this->blocks = true; SDL_RectEmpty(&this->physics.bounds); if (!Tile_initByType(this, tc, colorPrefix)) { free(this); return NULL; } return this; }
SDL_bool SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result) { int Amin, Amax, Bmin, Bmax; if (!A || !B || !result) { // TODO error message return SDL_FALSE; } /* Special cases for empty rects */ if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) { return SDL_FALSE; } /* Horizontal intersection */ Amin = A->x; Amax = Amin + A->w; Bmin = B->x; Bmax = Bmin + B->w; if (Bmin > Amin) Amin = Bmin; result->x = Amin; if (Bmax < Amax) Amax = Bmax; result->w = Amax - Amin; /* Vertical intersection */ Amin = A->y; Amax = Amin + A->h; Bmin = B->y; Bmax = Bmin + B->h; if (Bmin > Amin) Amin = Bmin; result->y = Amin; if (Bmax < Amax) Amax = Bmax; result->h = Amax - Amin; return !SDL_RectEmpty(result); }
static int SW_UpdateClipRect(SDL_Renderer * renderer) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; SDL_Surface *surface = data->surface; const SDL_Rect *rect = &renderer->clip_rect; if (surface) { if (!SDL_RectEmpty(rect)) { SDL_SetClipRect(surface, rect); } else { SDL_SetClipRect(surface, NULL); } } return 0; }
static int GLES_UpdateClipRect(SDL_Renderer * renderer) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; const SDL_Rect *rect = &renderer->clip_rect; if (SDL_CurrentContext != data->context) { /* We'll update the clip rect after we rebind the context */ return 0; } if (!SDL_RectEmpty(rect)) { data->glEnable(GL_SCISSOR_TEST); data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h); } else { data->glDisable(GL_SCISSOR_TEST); } return 0; }
static int DirectFB_UpdateClipRect(SDL_Renderer * renderer) { const SDL_Rect *rect = &renderer->clip_rect; DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata; IDirectFBSurface *destsurf = get_dfb_surface(data->window); DFBRegion region; if (!SDL_RectEmpty(rect)) { region.x1 = rect->x; region.x2 = rect->x + rect->w; region.y1 = rect->y; region.y2 = rect->y + rect->h; SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, ®ion)); } else { SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, NULL)); } return 0; error: return -1; }
bool Rect::isEmpty() const { SDL_Rect r; return SDL_RectEmpty(this->copyInto(&r)) == SDL_TRUE; }
void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done) { int i; static SDL_MouseMotionEvent lastEvent; if (state->verbose & VERBOSE_EVENT) { SDLTest_PrintEvent(event); } switch (event->type) { case SDL_WINDOWEVENT: switch (event->window.event) { case SDL_WINDOWEVENT_CLOSE: { SDL_Window *window = SDL_GetWindowFromID(event->window.windowID); if (window) { SDL_DestroyWindow(window); } } break; } break; case SDL_KEYDOWN: switch (event->key.keysym.sym) { /* Add hotkeys here */ case SDLK_PRINTSCREEN: { SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { for (i = 0; i < state->num_windows; ++i) { if (window == state->windows[i]) { SDLTest_ScreenShot(state->renderers[i]); } } } } break; case SDLK_EQUALS: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-+ double the size of the window */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { int w, h; SDL_GetWindowSize(window, &w, &h); SDL_SetWindowSize(window, w*2, h*2); } } break; case SDLK_MINUS: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-- half the size of the window */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { int w, h; SDL_GetWindowSize(window, &w, &h); SDL_SetWindowSize(window, w/2, h/2); } } break; case SDLK_c: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-C copy awesome text! */ SDL_SetClipboardText("SDL rocks!\nYou know it!"); printf("Copied text to clipboard\n"); } if (event->key.keysym.mod & KMOD_ALT) { /* Alt-C toggle a render clip rectangle */ for (i = 0; i < state->num_windows; ++i) { int w, h; if (state->renderers[i]) { SDL_Rect clip; SDL_GetWindowSize(state->windows[i], &w, &h); SDL_RenderGetClipRect(state->renderers[i], &clip); if (SDL_RectEmpty(&clip)) { clip.x = w/4; clip.y = h/4; clip.w = w/2; clip.h = h/2; SDL_RenderSetClipRect(state->renderers[i], &clip); } else { SDL_RenderSetClipRect(state->renderers[i], NULL); } } } } break; case SDLK_v: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-V paste awesome text! */ char *text = SDL_GetClipboardText(); if (*text) { printf("Clipboard: %s\n", text); } else { printf("Clipboard is empty\n"); } SDL_free(text); } break; case SDLK_g: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-G toggle grab */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE); } } break; case SDLK_m: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-M maximize */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { Uint32 flags = SDL_GetWindowFlags(window); if (flags & SDL_WINDOW_MAXIMIZED) { SDL_RestoreWindow(window); } else { SDL_MaximizeWindow(window); } } } break; case SDLK_r: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-R toggle mouse relative mode */ SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE); } break; case SDLK_z: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-Z minimize */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { SDL_MinimizeWindow(window); } } break; case SDLK_RETURN: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-Enter toggle fullscreen */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { Uint32 flags = SDL_GetWindowFlags(window); if (flags & SDL_WINDOW_FULLSCREEN) { SDL_SetWindowFullscreen(window, SDL_FALSE); } else { SDL_SetWindowFullscreen(window, SDL_TRUE); } } } else if (event->key.keysym.mod & KMOD_ALT) { /* Alt-Enter toggle fullscreen desktop */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { Uint32 flags = SDL_GetWindowFlags(window); if (flags & SDL_WINDOW_FULLSCREEN) { SDL_SetWindowFullscreen(window, SDL_FALSE); } else { SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); } } } break; case SDLK_b: if (event->key.keysym.mod & KMOD_CTRL) { /* Ctrl-B toggle window border */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { const Uint32 flags = SDL_GetWindowFlags(window); const SDL_bool b = ((flags & SDL_WINDOW_BORDERLESS) != 0) ? SDL_TRUE : SDL_FALSE; SDL_SetWindowBordered(window, b); } } break; case SDLK_0: if (event->key.keysym.mod & KMOD_CTRL) { SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window); } break; case SDLK_1: if (event->key.keysym.mod & KMOD_CTRL) { FullscreenTo(0, event->key.windowID); } break; case SDLK_2: if (event->key.keysym.mod & KMOD_CTRL) { FullscreenTo(1, event->key.windowID); } break; case SDLK_ESCAPE: *done = 1; break; case SDLK_SPACE: { char message[256]; SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); SDL_snprintf(message, sizeof(message), "(%i, %i), rel (%i, %i)\n", lastEvent.x, lastEvent.y, lastEvent.xrel, lastEvent.yrel); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Last mouse position", message, window); break; } default: break; } break; case SDL_QUIT: *done = 1; break; case SDL_MOUSEMOTION: lastEvent = event->motion; break; } }
/* The general purpose software blit routine */ static int SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { int okay; int src_locked; int dst_locked; /* Everything is okay at the beginning... */ okay = 1; /* Lock the destination if it's in hardware */ dst_locked = 0; if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { okay = 0; } else { dst_locked = 1; } } /* Lock the source if it's in hardware */ src_locked = 0; if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { okay = 0; } else { src_locked = 1; } } /* Set up source and destination buffer pointers, and BLIT! */ if (okay && !SDL_RectEmpty(srcrect)) { SDL_BlitFunc RunBlit; SDL_BlitInfo *info = &src->map->info; /* Set up the blit information */ info->src = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * info->src_fmt->BytesPerPixel; info->src_w = srcrect->w; info->src_h = srcrect->h; info->src_pitch = src->pitch; info->src_skip = info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel; info->dst = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel; info->dst_w = dstrect->w; info->dst_h = dstrect->h; info->dst_pitch = dst->pitch; info->dst_skip = info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel; RunBlit = (SDL_BlitFunc) src->map->data; /* Run the actual software blit */ RunBlit(info); } /* We need to unlock the surfaces if they're locked */ if (dst_locked) { SDL_UnlockSurface(dst); } if (src_locked) { SDL_UnlockSurface(src); } /* Blit is done! */ return (okay ? 0 : -1); }
int Splat_Render(Splat_Canvas *canvas) { if (!canvas) { Splat_SetError("Splat_Render: Invalid argument."); return -1; } int winwidth, winheight; SDL_Rect scaledRect; SDL_GetWindowSize(window, &winwidth, &winheight); /* Render to our framebuffer */ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); ERRCHECK(); glViewport(0, 0, viewportWidth, viewportHeight); ERRCHECK(); // Change to the projection matrix and set up our ortho view glMatrixMode(GL_PROJECTION); ERRCHECK(); glLoadIdentity(); ERRCHECK(); gluOrtho2D(0, viewportWidth, 0, viewportHeight); ERRCHECK(); // Set up modelview for 2D integer coordinates glMatrixMode(GL_MODELVIEW); ERRCHECK(); glLoadIdentity(); ERRCHECK(); glTranslatef(0.375f, viewportHeight + 0.375f, 0.0f); ERRCHECK(); glScalef(1.0f, -1.0f, 0.001f); ERRCHECK(); // Make the positive Z-axis point "out" from the view (e.g images at depth 4 will be higher than those at depth 0), and swap the Y axis // Clear the color and depth buffers. glClear(GL_COLOR_BUFFER_BIT); ERRCHECK(); // Enable textures and blending glEnable(GL_TEXTURE_2D); ERRCHECK(); glEnable(GL_BLEND); ERRCHECK(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ERRCHECK(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ERRCHECK(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ERRCHECK(); // Save the current matrix glPushMatrix(); ERRCHECK(); // Scale as necessary glScalef(canvas->scale[0], canvas->scale[1], 1.0f); ERRCHECK(); bool scaledCanvas = !(canvas->scale[0] == 1.0f && canvas->scale[1] == 1.0f); // Specify vertex and tex coord buffers glVertexPointer(3, GL_FLOAT, 0, vertex_buffer); ERRCHECK(); glEnableClientState(GL_VERTEX_ARRAY); ERRCHECK(); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_buffer); ERRCHECK(); glEnableClientState(GL_TEXTURE_COORD_ARRAY); ERRCHECK(); SDL_Rect viewRect; viewRect.x = canvas->origin.x; viewRect.y = canvas->origin.y; viewRect.w = viewportWidth; viewRect.h = viewportHeight; float depth = 0.0f; for (Splat_Layer *layer = canvas->layers; layer != NULL; layer = layer->next) { for (Splat_Instance *instance = layer->instances; instance != NULL; instance = instance->next) { //TODO do this once per texture // Bind our texture glBindTexture(GL_TEXTURE_2D, instance->texture); ERRCHECK(); if ((instance->flags & SPLAT_RELATIVE) != 0 && !SDL_HasIntersection(&instance->rect, &viewRect)) { continue; } // Save the current matrix glPushMatrix(); ERRCHECK(); // If relative, translate to the active canvas' current location if (instance->flags & SPLAT_RELATIVE) { glTranslatef(-canvas->origin.x, -canvas->origin.y, 0.0f); ERRCHECK(); } // Translate to the images current location glTranslatef(instance->rect.x, instance->rect.y, 0.0f); ERRCHECK(); // Set color for rendering glColor4ub(instance->color.r, instance->color.g, instance->color.b, instance->color.a); ERRCHECK(); // Scale the render rect scaledRect.x = instance->rect.x; scaledRect.y = instance->rect.y; scaledRect.w = instance->rect.w * instance->scale[0]; scaledRect.h = instance->rect.h * instance->scale[1]; // Handle rotation if (instance->flags & MASK_IMAGEMOD) { const float w2 = ((float) scaledRect.w) / 2.0f; const float h2 = ((float) scaledRect.h) / 2.0f; glTranslatef(w2, h2, 0.0f); ERRCHECK(); if (instance->flags & SPLAT_MIRROR_DIAG) { glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); ERRCHECK(); if ((instance->flags & SPLAT_MIRROR_X)) { glScalef(1.0f, -1.0f, 1.0f); ERRCHECK(); } if ((instance->flags & SPLAT_MIRROR_Y) == 0) { glScalef(-1.0f, 1.0f, 1.0f); ERRCHECK(); } } else { if (instance->flags & SPLAT_MIRROR_X) { glScalef(-1.0f, 1.0f, 1.0f); ERRCHECK(); } if (instance->flags & SPLAT_MIRROR_Y) { glScalef(1.0f, -1.0f, 1.0f); ERRCHECK(); } } if (instance->flags & SPLAT_ROTATE) { glRotatef(instance->angle, 0.0f, 0.0f, 1.0f); ERRCHECK(); } glTranslatef(-w2, -h2, 0.0f); ERRCHECK(); } // Handle scissoring if (!SDL_RectEmpty(&instance->clip)) { // Enable scissoring glEnable(GL_SCISSOR_TEST); ERRCHECK(); // Snip, snip, snip... if (scaledCanvas) { glScissor(instance->clip.x * canvas->scale[0], winheight - ((instance->clip.y + instance->clip.h) * canvas->scale[1]), instance->clip.w * canvas->scale[0], instance->clip.h * canvas->scale[1]); ERRCHECK(); } else { glScissor(instance->clip.x, winheight - (instance->clip.y + instance->clip.h), instance->clip.w, instance->clip.h); ERRCHECK(); } } else { // Disable scissoring glDisable(GL_SCISSOR_TEST); ERRCHECK(); } // Prepare to render triangles // First triangle //glTexCoord2f(instance->s1, instance->t2); texcoord_buffer[0] = instance->s1; texcoord_buffer[1] = instance->t2; //glVertex3f(0.0f, scaled_rect.h, depth); vertex_buffer[0] = 0.0f; vertex_buffer[1] = scaledRect.h; vertex_buffer[2] = depth; //glTexCoord2f(instance->s1, instance->t1); texcoord_buffer[2] = instance->s1; texcoord_buffer[3] = instance->t1; //glVertex3f(0.0f, 0.0f, depth); vertex_buffer[3] = 0.0f; vertex_buffer[4] = 0.0f; vertex_buffer[5] = depth; //glTexCoord2f(instance->s2, instance->t1); texcoord_buffer[4] = instance->s2; texcoord_buffer[5] = instance->t1; //glVertex3f(scaled_rect.w, 0.0f, depth); vertex_buffer[6] = scaledRect.w; vertex_buffer[7] = 0.0f; vertex_buffer[8] = depth; // Second triangle //glTexCoord2f(instance->s2, instance->t2); texcoord_buffer[6] = instance->s2; texcoord_buffer[7] = instance->t2; //glVertex3f(scaled_rect.w, scaled_rect.h, depth); vertex_buffer[9] = scaledRect.w; vertex_buffer[10] = scaledRect.h; vertex_buffer[11] = depth; //glTexCoord2f(instance->s1, instance->t2); texcoord_buffer[8] = instance->s1; texcoord_buffer[9] = instance->t2; //glVertex3f(0.0f, scaled_rect.h, depth); vertex_buffer[12] = 0.0f; vertex_buffer[13] = scaledRect.h; vertex_buffer[14] = depth; //glTexCoord2f(instance->s2, instance->t1); texcoord_buffer[10] = instance->s2; texcoord_buffer[11] = instance->t1; //glVertex3f(scaled_rect.w, 0.0f, depth); vertex_buffer[15] = scaledRect.w; vertex_buffer[16] = 0.0f; vertex_buffer[17] = depth; // Finished with our triangles glDrawArrays(GL_TRIANGLES, 0, 6); ERRCHECK(); // Finished with our triangles glPopMatrix(); ERRCHECK(); } depth += 1.0f; } // Disable scissoring glDisable(GL_SCISSOR_TEST); ERRCHECK(); uint32_t time = SDL_GetTicks(); // Draw rects if (canvas->rects) { glDisable(GL_TEXTURE_2D); ERRCHECK(); glEnableClientState(GL_VERTEX_ARRAY); ERRCHECK(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); ERRCHECK(); glVertexPointer(2, GL_FLOAT, 0, &vertex_buffer); ERRCHECK(); for (Splat_Rect *prev = NULL, *curr = canvas->rects; curr != NULL; /**/) { glColor4ub(curr->color.r, curr->color.g, curr->color.b, curr->color.a); ERRCHECK(); // Save the current matrix glPushMatrix(); ERRCHECK(); if (!curr->relative) { // Translate to the active canvas's current location glTranslatef(-canvas->origin.x, -canvas->origin.y, 0.0f); ERRCHECK(); } glLineWidth(curr->width); ERRCHECK(); // Prepare to render rects if (curr->fill) { // First triangle vertex_buffer[0] = curr->x1; vertex_buffer[1] = curr->y1; vertex_buffer[2] = curr->x2; vertex_buffer[3] = curr->y1; vertex_buffer[4] = curr->x1; vertex_buffer[5] = curr->y2; // Second triangle vertex_buffer[6] = curr->x2; vertex_buffer[7] = curr->y2; vertex_buffer[8] = curr->y1; vertex_buffer[9] = curr->y2; vertex_buffer[10] = curr->x2; vertex_buffer[11] = curr->x1; // Finished with our triangles glDrawArrays(GL_TRIANGLES, 0, 6); ERRCHECK(); } else { vertex_buffer[0] = curr->x1; vertex_buffer[1] = curr->y1; vertex_buffer[2] = curr->x2; vertex_buffer[3] = curr->y1; vertex_buffer[4] = curr->x2; vertex_buffer[5] = curr->y2; vertex_buffer[6] = curr->x1; vertex_buffer[7] = curr->y2; // Finished with our lines glDrawArrays(GL_LINE_LOOP, 0, 4); ERRCHECK(); } // Restore the old matrix glPopMatrix(); ERRCHECK(); // Expire old rects if (time >= curr->ttl) { if (prev) { prev->next = curr->next; } else { canvas->rects = curr->next; } Splat_Rect *old = curr; curr = curr->next; free(old); } else { prev = curr; curr = curr->next; } } } if (canvas->lines) { glDisable(GL_TEXTURE_2D); ERRCHECK(); glEnableClientState(GL_VERTEX_ARRAY); ERRCHECK(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); ERRCHECK(); for (Splat_Line *prev = NULL, *curr = canvas->lines; curr != NULL; /**/) { glColor4ub(curr->color.r, curr->color.g, curr->color.b, curr->color.a); ERRCHECK(); if (!curr->relative) { // Translate to the active canvas's current location glTranslatef(-canvas->origin.x, -canvas->origin.y, 0.0f); ERRCHECK(); } glLineWidth(curr->width); ERRCHECK(); glVertexPointer(2, GL_FLOAT, 0, &curr->start.x); ERRCHECK(); // Finished with our triangles glDrawArrays(GL_LINES, 0, 2); ERRCHECK(); // Expire old lines if (time >= curr->ttl) { if (prev) { prev->next = curr->next; } else { canvas->lines = curr->next; } Splat_Line *old = curr; curr = curr->next; free(old); } else { prev = curr; curr = curr->next; } } } // Restore original, non-scaled matrix glPopMatrix(); ERRCHECK(); // Render to the screen glBindFramebuffer(GL_FRAMEBUFFER, 0); ERRCHECK(); glViewport(0, 0, winwidth, winheight); ERRCHECK(); // Render on the whole framebuffer, complete from the lower left corner to the upper right glDisable(GL_BLEND); ERRCHECK(); glEnable(GL_TEXTURE_2D); ERRCHECK(); // Specify vertex and tex coord buffers glVertexPointer(3, GL_FLOAT, 0, vertex_buffer); ERRCHECK(); glEnableClientState(GL_VERTEX_ARRAY); ERRCHECK(); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_buffer); ERRCHECK(); glEnableClientState(GL_TEXTURE_COORD_ARRAY); ERRCHECK(); // Change to the projection matrix and set up our ortho view glMatrixMode(GL_PROJECTION); ERRCHECK(); glLoadIdentity(); ERRCHECK(); gluOrtho2D(0, winwidth, 0, winheight); ERRCHECK(); // Set up modelview for 2D integer coordinates glMatrixMode(GL_MODELVIEW); ERRCHECK(); glLoadIdentity(); ERRCHECK(); glTranslatef(0.375f, winheight + 0.375f, 0.0f); ERRCHECK(); glScalef(1.0f, -1.0f, 0.001f); ERRCHECK(); // Make the positive Z-axis point "out" from the view (e.g images at depth 4 will be higher than those at depth 0), and swap the Y axis glBindTexture(GL_TEXTURE_2D, frameTexture); ERRCHECK(); glColor4ub(255, 255, 255, 255); ERRCHECK(); #ifdef SPLAT_SHADERS_EXPERIMENTAL glUseProgram(shaderProgram); ERRCHECK(); if (shaderProgram) { float size[2]; GLint uniform; size[0] = viewportWidth; size[1] = viewportHeight; uniform = glGetUniformLocation(shaderProgram, "rubyInputSize"); ERRCHECK(); glUniform2fv(uniform, 1, size); ERRCHECK(); uniform = glGetUniformLocation(shaderProgram, "rubyTextureSize"); ERRCHECK(); glUniform2fv(uniform, 1, size); ERRCHECK(); size[0] = winwidth; size[1] = winheight; uniform = glGetUniformLocation(shaderProgram, "rubyOutputSize"); ERRCHECK(); glUniform2fv(uniform, 1, size); ERRCHECK(); } #endif // SPLAT_SHADERS_EXPERIMENTAL // First triangle //glTexCoord2f(handle->s1, handle->t2); texcoord_buffer[0] = 0.0f; texcoord_buffer[1] = 0.0f; //glVertex3f(0.0f, scaled_rect.h, handle->depth); vertex_buffer[0] = 0.0f; vertex_buffer[1] = (float) winheight; vertex_buffer[2] = 0.0f; //glTexCoord2f(handle->s1, handle->t1); texcoord_buffer[2] = 0.0f; texcoord_buffer[3] = 1.0f; //glVertex3f(0.0f, 0.0f, handle->depth); vertex_buffer[3] = 0.0f; vertex_buffer[4] = 0.0f; vertex_buffer[5] = 0.0f; //glTexCoord2f(handle->s2, handle->t1); texcoord_buffer[4] = 1.0f; texcoord_buffer[5] = 1.0f; //glVertex3f(scaled_rect.w, 0.0f, handle->depth); vertex_buffer[6] = (float) winwidth; vertex_buffer[7] = 0.0f; vertex_buffer[8] = 0.0f; // Second triangle //glTexCoord2f(handle->s2, handle->t2); texcoord_buffer[6] = 1.0f; texcoord_buffer[7] = 0.0f; //glVertex3f(scaled_rect.w, scaled_rect.h, handle->depth); vertex_buffer[9] = (float) winwidth; vertex_buffer[10] = (float) winheight; vertex_buffer[11] = 0.0f; //glTexCoord2f(handle->s1, handle->t2); texcoord_buffer[8] = 0.0f; texcoord_buffer[9] = 0.0f; //glVertex3f(0.0f, scaled_rect.h, handle->depth); vertex_buffer[12] = 0.0f; vertex_buffer[13] = (float) winheight; vertex_buffer[14] = 0.0f; //glTexCoord2f(handle->s2, handle->t1); texcoord_buffer[10] = 1.0f; texcoord_buffer[11] = 1.0f; //glVertex3f(scaled_rect.w, 0.0f, handle->depth); vertex_buffer[15] = (float) winwidth; vertex_buffer[16] = 0.0f; vertex_buffer[17] = 0.0f; // Finished with our triangles glDrawArrays(GL_TRIANGLES, 0, 6); ERRCHECK(); #ifdef SPLAT_SHADERS_EXPERIMENTAL glUseProgram(0); ERRCHECK(); #endif // SPLAT_SHADERS_EXPERIMENTAL // Finish rendering by swap buffers SDL_GL_SwapWindow(window); #if ENABLE_FPS_LOG fps_lastframe = fps_frametime; fps_frametime = SDL_GetTicks(); Uint32 current_fps = 1.0f / (((float) (fps_frametime - fps_lastframe)) / 1000.0f); fps_max = current_fps > fps_max ? current_fps : fps_max; fps_min = current_fps < fps_min ? current_fps : fps_min; fps_times[fps_index] = current_fps; fps_index++; if (fps_index > MAX_FPS_INDEX) { fps_index = 0; } if (fps_frametime > fps_next_update) { Uint32 i, total = 0, fps; for (i = 0; i < MAX_FPS_INDEX; i++) { total += fps_times[i]; } fps = total / MAX_FPS_INDEX; printf("FPS: %d (%d to %d)\n", fps, fps_min, fps_max); // Reset min/max and set next print time fps_min = (Uint32) -1; fps_max = 0; fps_next_update = fps_frametime + 2000; } #endif return 0; }
SDL_bool SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip, SDL_Rect * result) { int minx = 0; int miny = 0; int maxx = 0; int maxy = 0; int x, y, i; if (!points) { SDL_InvalidParamError("points"); return SDL_FALSE; } if (count < 1) { SDL_InvalidParamError("count"); return SDL_FALSE; } if (clip) { SDL_bool added = SDL_FALSE; const int clip_minx = clip->x; const int clip_miny = clip->y; const int clip_maxx = clip->x+clip->w-1; const int clip_maxy = clip->y+clip->h-1; /* Special case for empty rectangle */ if (SDL_RectEmpty(clip)) { return SDL_FALSE; } for (i = 0; i < count; ++i) { x = points[i].x; y = points[i].y; if (x < clip_minx || x > clip_maxx || y < clip_miny || y > clip_maxy) { continue; } if (!added) { /* Special case: if no result was requested, we are done */ if (result == NULL) { return SDL_TRUE; } /* First point added */ minx = maxx = x; miny = maxy = y; added = SDL_TRUE; continue; } if (x < minx) { minx = x; } else if (x > maxx) { maxx = x; } if (y < miny) { miny = y; } else if (y > maxy) { maxy = y; } } if (!added) { return SDL_FALSE; } } else { /* Special case: if no result was requested, we are done */ if (result == NULL) { return SDL_TRUE; } /* No clipping, always add the first point */ minx = maxx = points[0].x; miny = maxy = points[0].y; for (i = 1; i < count; ++i) { x = points[i].x; y = points[i].y; if (x < minx) { minx = x; } else if (x > maxx) { maxx = x; } if (y < miny) { miny = y; } else if (y > maxy) { maxy = y; } } } if (result) { result->x = minx; result->y = miny; result->w = (maxx-minx)+1; result->h = (maxy-miny)+1; } return SDL_TRUE; }
SDL_bool SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2, int *Y2) { int x = 0; int y = 0; int x1, y1; int x2, y2; int rectx1; int recty1; int rectx2; int recty2; int outcode1, outcode2; if (!rect) { SDL_InvalidParamError("rect"); return SDL_FALSE; } if (!X1) { SDL_InvalidParamError("X1"); return SDL_FALSE; } if (!Y1) { SDL_InvalidParamError("Y1"); return SDL_FALSE; } if (!X2) { SDL_InvalidParamError("X2"); return SDL_FALSE; } if (!Y2) { SDL_InvalidParamError("Y2"); return SDL_FALSE; } /* Special case for empty rect */ if (SDL_RectEmpty(rect)) { return SDL_FALSE; } x1 = *X1; y1 = *Y1; x2 = *X2; y2 = *Y2; rectx1 = rect->x; recty1 = rect->y; rectx2 = rect->x + rect->w - 1; recty2 = rect->y + rect->h - 1; /* Check to see if entire line is inside rect */ if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 && y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) { return SDL_TRUE; } /* Check to see if entire line is to one side of rect */ if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) || (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) { return SDL_FALSE; } if (y1 == y2) { /* Horizontal line, easy to clip */ if (x1 < rectx1) { *X1 = rectx1; } else if (x1 > rectx2) { *X1 = rectx2; } if (x2 < rectx1) { *X2 = rectx1; } else if (x2 > rectx2) { *X2 = rectx2; } return SDL_TRUE; } if (x1 == x2) { /* Vertical line, easy to clip */ if (y1 < recty1) { *Y1 = recty1; } else if (y1 > recty2) { *Y1 = recty2; } if (y2 < recty1) { *Y2 = recty1; } else if (y2 > recty2) { *Y2 = recty2; } return SDL_TRUE; } /* More complicated Cohen-Sutherland algorithm */ outcode1 = ComputeOutCode(rect, x1, y1); outcode2 = ComputeOutCode(rect, x2, y2); while (outcode1 || outcode2) { if (outcode1 & outcode2) { return SDL_FALSE; } if (outcode1) { if (outcode1 & CODE_TOP) { y = recty1; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode1 & CODE_BOTTOM) { y = recty2; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode1 & CODE_LEFT) { x = rectx1; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } else if (outcode1 & CODE_RIGHT) { x = rectx2; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } x1 = x; y1 = y; outcode1 = ComputeOutCode(rect, x, y); } else { if (outcode2 & CODE_TOP) { y = recty1; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode2 & CODE_BOTTOM) { y = recty2; x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); } else if (outcode2 & CODE_LEFT) { x = rectx1; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } else if (outcode2 & CODE_RIGHT) { x = rectx2; y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); } x2 = x; y2 = y; outcode2 = ComputeOutCode(rect, x, y); } } *X1 = x1; *Y1 = y1; *X2 = x2; *Y2 = y2; return SDL_TRUE; }