commit ee0f4f0f2c11a96f7f92e565c4c8e39cb2b64e20 Author: Miloslav Číž Date: Sat Nov 17 13:34:15 2018 +0100 Init diff --git a/make.sh b/make.sh new file mode 100755 index 0000000..6e5b564 --- /dev/null +++ b/make.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +PROGRAM=testSDL + +clear; clear; g++ -x c -g -fmax-errors=5 -pedantic -Wall -Wextra -o $PROGRAM $PROGRAM.c -lSDL2 2>&1 >/dev/null && ./$PROGRAM diff --git a/s3l.h b/s3l.h new file mode 100644 index 0000000..9bf23b7 --- /dev/null +++ b/s3l.h @@ -0,0 +1,196 @@ +#ifndef S3L_H +#define S3L_H + +#include + +typedef int16_t S3L_COORD; + +typedef struct +{ + int16_t x; + int16_t y; +} S3L_PixelInfo; + +typedef struct +{ + int16_t steps; + int16_t err; + int16_t x; + int16_t y; + + int16_t *majorCoord; + int16_t *minorCoord; + int16_t majorIncrement; + int16_t minorIncrement; + int16_t majorDiff; + int16_t minorDiff; +} S3L_BresenhamState; + +static inline int16_t S3L_abs(int16_t value) +{ + return value >= 0 ? value : -1 * value; +} + +void S3L_bresenhamInit(S3L_BresenhamState *state, int16_t x0, int16_t y0, int16_t x1, int16_t y1) +{ + int16_t dx = x1 - x0; + int16_t dy = y1 - y0; + + int16_t absDx = S3L_abs(dx); + int16_t absDy = S3L_abs(dy); + + if (absDx >= absDy) + { + state->majorCoord = &(state->x); + state->minorCoord = &(state->y); + + state->minorDiff = 2 * absDy; + state->majorDiff = 2 * absDx; + state->err = 2 * dy - dx; + + state->majorIncrement = dx >= 0 ? 1 : -1; + state->minorIncrement = dy >= 0 ? 1 : -1; + + state->steps = absDx; + } + else + { + state->majorCoord = &(state->y); + state->minorCoord = &(state->x); + + state->minorDiff = 2 * absDx; + state->majorDiff = 2 * absDy; + state->err = 2 * dx - dy; + + state->majorIncrement = dy >= 0 ? 1 : -1; + state->minorIncrement = dx >= 0 ? 1 : -1; + + state->steps = absDy; + } + + state->x = x0; + state->y = y0; +} + +int S3L_bresenhamStep(S3L_BresenhamState *state) +{ + state->steps--; + + (*state->majorCoord) += state->majorIncrement; + + if (state->err > 0) + { + (*state->minorCoord) += state->minorIncrement; + state->err -= state->majorDiff; + } + + state->err += state->minorDiff; + + return state->steps >= 0; +} + +void S3L_drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + S3L_COORD + tPointX, tPointY, // top triangle point coords + lPointX, lPointY, // left triangle point coords + rPointX, rPointY; // right triangle point coords + + // Sort the points. + + #define handleLR(a,b)\ + if (x##a <= x##b)\ + {\ + lPointX = x##a; lPointY = y##a;\ + rPointX = x##b; rPointY = y##b;\ + }\ + else\ + {\ + lPointX = x##b; lPointY = y##b;\ + rPointX = x##a; rPointY = y##a;\ + } + + if (y0 <= y1) + { + if (y0 <= y2) + { + tPointX = x0; + tPointY = y0; + handleLR(1,2) + } + else + { + tPointX = x2; + tPointY = y2; + handleLR(0,1) + } + } + else + { + if (y1 <= y2) + { + tPointX = x1; + tPointY = y1; + handleLR(0,2) + } + else + { + tPointX = x2; + tPointY = y2; + handleLR(0,1) + } + } + + // Now drive the triangle line by line. + + #undef handleLR + + S3L_COORD currentY = tPointY; + + /* We'll be using a slight modification of Bresenham line algorithm (a one + that draws a _non-continous_ line). */ + + #define initSide(s)\ + int16_t s##X = tPointX;\ + int16_t s##Dx = s##PointX - tPointX;\ + int16_t s##Dy = s##PointY - tPointY;\ + int16_t s##Inc = s##Dx >= 0 ? 1 : -1;\ + int16_t s##Err = 2 * s##Dx - s##Dy;\ + int16_t s##ErrAdd = 2 * S3L_abs(s##Dx);\ + int16_t s##ErrSub = 2 * S3L_abs(s##Dy); + + #define stepSide(s)\ + while (s##Err > 0)\ + {\ + s##X += s##Inc;\ + s##Err -= s##ErrSub;\ + }\ + s##Err += s##ErrAdd; + + initSide(r) + initSide(l) + + S3L_PixelInfo p; + + while (currentY <= rPointY) + { + p.y = currentY; + + for (S3L_COORD x = lX; x <= rX; ++x) + { + p.x = x; + S3L_PIXEL_FUNCTION(&p); + } + + stepSide(r) + stepSide(l) + + ++currentY; + } + + #undef initSide + #undef stepSide + +} + +#endif diff --git a/testSDL.c b/testSDL.c new file mode 100644 index 0000000..1306d2c --- /dev/null +++ b/testSDL.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#define S3L_PIXEL_FUNCTION drawPixel + +#include "s3l.h" + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +uint32_t pixels[SCREEN_WIDTH * SCREEN_HEIGHT]; + +uint32_t frame = 0; + +void clearScreen() +{ + memset(pixels,0,SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(uint32_t)); +} + +static inline void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue) +{ + uint32_t r = red & 0x000000FF; + r = r << 16; + + uint32_t g = green & 0x000000FF; + g = g << 8; + + uint32_t b = blue & 0x000000FF; + + pixels[y * SCREEN_WIDTH + x] = r | g | b; +} + +void drawPixel(S3L_PixelInfo *p) +{ + setPixel(p->x,p->y,255,255,0); +} + +void draw() +{ + clearScreen(); + + setPixel(90,50,255,0,0); + setPixel(100,10,255,0,0); + setPixel(300,80,255,0,0); + + S3L_drawTriangle(90,50,100,10,300,80); +} + +int main() +{ + SDL_Window *window = SDL_CreateWindow("test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,0); + SDL_Texture *texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT); + SDL_Surface *screenSurface = SDL_GetWindowSurface(window); + SDL_Event event; + + int running = 1; + + while (running) + { + draw(); + SDL_UpdateTexture(texture,NULL,pixels,SCREEN_WIDTH * sizeof(uint32_t)); + + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + running = 0; + break; + + default: + break; + } + } + + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer,texture,NULL,NULL); + SDL_RenderPresent(renderer); + + frame++; + } + + return 0; +}