aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--cube3D.c240
2 files changed, 247 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..61b9d92
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# Cube3D
+É um programa simples que utiliza da biblioteca SDL para desenhar um cubo e rotacionĂ¡-lo.
+
+Para compilar:
+'''
+gcc cube3D.c $(pkgconf --cflags --libs sdl2) -lm
+''' \ No newline at end of file
diff --git a/cube3D.c b/cube3D.c
new file mode 100644
index 0000000..8e6d1cb
--- /dev/null
+++ b/cube3D.c
@@ -0,0 +1,240 @@
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_error.h>
+#include <SDL2/SDL_pixels.h>
+#include <SDL2/SDL_stdinc.h>
+#include <SDL2/SDL_video.h>
+#include <math.h>
+#include <stdbool.h>
+#define MAX(a, b)(a>b?a:b)
+#define MIN(a, b)(a<b?a:b)
+
+#define WIDTH 640
+#define HEIGHT 640
+
+SDL_Window *win;
+SDL_Surface *winSurf;
+
+typedef struct{
+ double x, y;
+}point;
+
+typedef struct{
+ int x, y;
+}pointDraw;
+
+typedef struct{
+ double x, y, z;
+}point3D;
+
+int init();
+void kill();
+pointDraw map(point p);
+point p3d2p(point3D p);
+void DrawPixel(SDL_Surface* screen, pointDraw p, Uint32 color);
+void DrawLine(pointDraw a, pointDraw b, Uint32 color);
+void drawCube();
+void rotateCube(double a, double b, double c);
+void DrawEixos();
+
+bool loop();
+
+point3D cubo3D[8];
+
+int main(int argc, char* argv[]){
+ init();
+ cubo3D[0].x = -0.5 ; cubo3D[0].y = 0.5; cubo3D[0].z = -0.5;
+ cubo3D[1].x = 0.5; cubo3D[1].y = 0.5; cubo3D[1].z = -0.5;
+ cubo3D[2].x = 0.5; cubo3D[2].y = -0.5 ; cubo3D[2].z = -0.5;
+ cubo3D[3].x = -0.5 ; cubo3D[3].y = -0.5 ; cubo3D[3].z = -0.5;
+ cubo3D[4].x = -0.5 ; cubo3D[4].y = 0.5; cubo3D[4].z = 0.5;
+ cubo3D[5].x = 0.5; cubo3D[5].y = 0.5; cubo3D[5].z = 0.5;
+ cubo3D[6].x = 0.5; cubo3D[6].y = -0.5 ; cubo3D[6].z = 0.5;
+ cubo3D[7].x = -0.5; cubo3D[7].y = -0.5 ; cubo3D[7].z = 0.5;
+
+ // point p1 = {-1, -1};
+ // point p2 = {0, 0};
+ // printf("%d %d\n%d %d\n", map(p1).x, map(p1).y, map(p2).x, map(p2).y);
+ //DrawLine(map(p1), map(p2));
+ drawCube();
+ while(loop()){
+ SDL_Delay(10);
+ }
+ //winSurf->pixels = pixels;
+ //SDL_UpdateWindowSurface(win);
+
+ // getchar();
+ kill();
+}
+
+void DrawEixos(){
+ pointDraw a = {320, 0};
+ pointDraw b = {320, 640};
+ DrawLine(a, b, 0xFFFFFF);
+ pointDraw c = {0, 320};
+ pointDraw d = {640, 320};
+ DrawLine(c, d, 0xFFFFFF);
+}
+
+void rotateCube(double a, double b, double c){
+ double Rx[3][3] = {{cos(a), -sin(a), 0},{sin(a), cos(a), 0},{0, 0, 1}};
+ double Ry[3][3] = {{cos(b), 0, sin(b)}, {0, 1, 0}, {-sin(b), 0, cos(b)}};
+ double Rz[3][3] = {{1, 0, 0}, {0, cos(c), -sin(c)}, {0, sin(c), cos(c)}};
+ for(int i=0; i<8; ++i){
+ point3D tmp = cubo3D[i];
+ cubo3D[i].x = Rx[0][0]*tmp.x + Rx[0][1]*tmp.y + Rx[0][2]*tmp.z;
+ cubo3D[i].y = Rx[1][0]*tmp.x + Rx[1][1]*tmp.y + Rx[1][2]*tmp.z;
+ cubo3D[i].z = Rx[2][0]*tmp.x + Rx[2][1]*tmp.y + Rx[2][2]*tmp.z;
+
+ tmp = cubo3D[i];
+ cubo3D[i].x = Ry[0][0]*tmp.x + Ry[0][1]*tmp.y + Ry[0][2]*tmp.z;
+ cubo3D[i].y = Ry[1][0]*tmp.x + Ry[1][1]*tmp.y + Ry[1][2]*tmp.z;
+ cubo3D[i].z = Ry[2][0]*tmp.x + Ry[2][1]*tmp.y + Ry[2][2]*tmp.z;
+
+ tmp = cubo3D[i];
+ cubo3D[i].x = Rz[0][0]*tmp.x + Rz[0][1]*tmp.y + Rz[0][2]*tmp.z;
+ cubo3D[i].y = Rz[1][0]*tmp.x + Rz[1][1]*tmp.y + Rz[1][2]*tmp.z;
+ cubo3D[i].z = Rz[2][0]*tmp.x + Rz[2][1]*tmp.y + Rz[2][2]*tmp.z;
+ }
+}
+
+void drawCube(){
+ for(int i=0; i<4; ++i){
+ if(i != 3){
+ DrawLine(map(p3d2p(cubo3D[i])), map(p3d2p(cubo3D[i+1])), 0x00FF00);
+ DrawLine(map(p3d2p(cubo3D[i+4])), map(p3d2p(cubo3D[i+5])), 0x00FF00);
+ }else{
+ DrawLine(map(p3d2p(cubo3D[i])), map(p3d2p(cubo3D[0])), 0x00FF00);
+ DrawLine(map(p3d2p(cubo3D[i+4])), map(p3d2p(cubo3D[4])), 0x00FF00);
+ }
+ DrawLine(map(p3d2p(cubo3D[i])), map(p3d2p(cubo3D[i+4])), 0x00FF00);
+ }
+}
+
+point p3d2p(point3D p){
+ point r;
+ r.x = p.x;
+ r.y = p.y;
+ return r;
+}
+
+pointDraw map(point p){
+ pointDraw r;
+ r.x = 320*(p.x+1);
+ r.y = -320*(p.y+1)+640;
+ return r;
+}
+
+bool loop(){
+ SDL_Event event;
+
+ while(SDL_PollEvent(&event) != 0){
+ switch(event.type){
+ case SDL_QUIT:
+ return false;
+ }
+ }
+ SDL_FillRect(winSurf, NULL, 0x000000);
+ DrawEixos();
+ drawCube();
+
+ rotateCube(0.005, 0.005, 0.005);
+
+
+ SDL_UpdateWindowSurface(win);
+ return true;
+}
+
+
+
+void DrawLine(pointDraw a, pointDraw b, Uint32 color){
+ int dx = abs(a.x - b.x);
+ int dy = abs(a.y - b.y);
+
+
+ if(dx >= dy && dx != 0){
+ double m = 1.0*(a.y-b.y)/(a.x - b.x);
+ double q = a.y - m * a.x;
+
+ int xmin = MIN(a.x, b.x);
+ int xmax = a.x + b.x - xmin;
+
+ pointDraw p;
+ for(int i=xmin; i < xmax; ++i){
+ p.x = i;
+ double tmp = m * p.x + q;
+
+ if(tmp - (int)tmp <= 0.5) p.y = (int) tmp;
+ else p.y = (int) tmp + 1;
+
+ DrawPixel(winSurf, p, color);
+ }
+ }else{
+ //double m1 = 1.0*(a.x-b.x)/(a.y-b.y);
+
+ if(a.x-b.x != 0){
+ double m = 1.0*(a.y-b.y)/(a.x - b.x);
+ double q = a.y - m * a.x;
+
+ int ymin = MIN(a.y, b.y);
+ int ymax = a.y + b.y - ymin;
+
+ pointDraw p;
+ for(int i=ymin; i<ymax; ++i){
+ p.y = i;
+ double tmp = (p.y-q)/m;
+
+ if(tmp - (int)tmp <= 0.5) p.x = (int) tmp;
+ else p.x = (int) tmp + 1;
+
+ DrawPixel(winSurf, p, color);
+ }
+ }else{
+ int ymin = MIN(a.y, b.y);
+ int ymax = a.y + b.y - ymin;
+
+ pointDraw p;
+ p.x = a.x;
+ for(int i=ymin; i<ymax; ++i){
+ p.y = i;
+ DrawPixel(winSurf, p, color);
+ }
+ }
+ }
+}
+
+void DrawPixel(SDL_Surface* screen, pointDraw p, Uint32 color){
+ if(p.x > 640 || p.x < 0 || p.y > 640 || p.y < 0) return;
+
+ Uint32 *pixels = (Uint32*)screen->pixels;
+ Uint32 *pixel = pixels + p.y * screen->pitch/4 + p.x;
+ //*pixel = SDL_MapRGB(screen->format, 0xFF, 0x00, 0x00);
+ *pixel = color;
+}
+
+int init(){
+ if(SDL_Init(SDL_INIT_EVERYTHING) < 0){
+ printf("ERRO: Nao foi possivel iniciar o SDL:\n\t%s\n", SDL_GetError());
+ return 0;
+ }
+
+ win = SDL_CreateWindow("3DCube",
+ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
+ if(!win){
+ printf("ERRO: Nao foi possibel criar uma janela:\n\t%s\n", SDL_GetError());
+ return 0;
+ }
+
+ winSurf = SDL_GetWindowSurface(win);
+ if(!winSurf){
+ printf("ERRO: Nao foi possivel pegar a surface da janela:\n\t%s\n", SDL_GetError());
+ return 0;
+ }
+
+ return 1;
+}
+
+void kill(){
+ SDL_DestroyWindow(win);
+ SDL_Quit();
+}