ultimecia

A ps1 emulator in c
Log | Files | Refs

commit 4c129482be98fe54516eff50bb117872ef96a033
parent 949276287319d0559604f299a9029ed3c44a833a
Author: root <root@lunarcry>
Date:   Sat, 19 Oct 2024 20:56:53 +0000

SR: Added triangle function:
triangle(vertex 1, vertex 2, vertex3, color) -- draws the triangle

Diffstat:
Msrc/sr/sr.c | 316+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 164 insertions(+), 152 deletions(-)

diff --git a/src/sr/sr.c b/src/sr/sr.c @@ -7,111 +7,120 @@ #include <math.h> #include <SDL2/SDL.h> -#define W 512 -#define H 512 +#define W 1024 +#define H 1024 #define WIN_W 1024 #define WIN_H 1024 #define VEC2I_SWAP(x, y) { ivec2 temp = x; x = y; y = temp; } +#define I_SWAP(x, y) { int temp = x; x = y; y = temp; } typedef void v; typedef uint8_t u8;typedef uint16_t u16;typedef uint32_t u32;typedef uint64_t u64;typedef int8_t i8;typedef int16_t i16;typedef int32_t i32;typedef int64_t i64;typedef uint8_t Bool; typedef struct { u32 *data; } FB; typedef struct {u8 b;u8 g;u8 r; u8 a;} C; - -typedef struct { - double x, y, z; -} point; - -typedef struct { - int x, y; -} ivec2; - -typedef struct { - double x, y, z; -} vec3f; - -typedef struct { - -} scene; - +typedef struct { double x, y, z; } point; +typedef struct { int x, y; } ivec2; +typedef struct { double x, y, z; } vec3f; enum mop {ADD, SUB, MUL, DIV}; FB fb; SDL_Window* win; SDL_Renderer* ren; vec3f **vertices; -int **faces; +i32 **faces; + +void +FB_flip_vert(u32 *data) +{ + u64 bytes_per_line; u32 *line; i32 half, j; + + bytes_per_line = W; + line = (u32 *)malloc(bytes_per_line * sizeof(u32)); + half = H>>1; + + for (i32 j=0; j<half; j++) { + u64 l1 = j*bytes_per_line; + u64 l2 = (H-1-j)*bytes_per_line; + memmove((void *)line, (void *)(data+l1), bytes_per_line* sizeof(u32)); + memmove((void *)(data+l1), (void *)(data+l2), bytes_per_line* sizeof(u32)); + memmove((void *)(data+l2), (void *)line, bytes_per_line* sizeof(u32)); + } + free(line); +} ivec2 IVEC2_op(ivec2 a, ivec2 b, enum mop mop) { - - ivec2 c; - switch(mop) { - case ADD: - c.x = a.x + b.x; - c.y = a.y + b.y; - break; - case SUB: - c.x = a.x - b.x; - c.y = a.y - b.y; - break; - case MUL: - c.x = a.x * b.x; - c.y = a.y * b.y; - break; - default: - break; - } - return c; + ivec2 c; + switch(mop) { + case ADD: + c.x = a.x + b.x; + c.y = a.y + b.y; + break; + case SUB: + c.x = a.x - b.x; + c.y = a.y - b.y; + break; + case MUL: + c.x = a.x * b.x; + c.y = a.y * b.y; + break; + default: + break; + } + return c; } + ivec2 -IVEC2_ops(ivec2 a, int b, enum mop mop) +IVEC2_ops(ivec2 a, i32 b, enum mop mop) { - ivec2 c; - switch(mop) { - case ADD: - c.x = a.x + b; - c.y = a.y + b; - break; - case SUB: - c.x = a.x - b; - c.y = a.y - b; - break; - case MUL: - c.x = a.x * b; - c.y = a.y * b; - break; - default: - break; - } - return c; + ivec2 c; + switch(mop) { + case ADD: + c.x = a.x + b; + c.y = a.y + b; + break; + case SUB: + c.x = a.x - b; + c.y = a.y - b; + break; + case MUL: + c.x = a.x * b; + c.y = a.y * b; + break; + default: + break; + } + return c; } -C* -new_C(u32 b) +C +C_new(u32 b) { - C* c = malloc(sizeof(C)); - c->r = (u8)(b & 0xff); - c->g = (u8)((b >> 8) & 0xff); - c->b = (u8)((b >> 16) & 0xff); - c->a = (u8)((b >> 24) & 0xff); + C c; + c.r = (u8)(b & 0xff); + c.g = (u8)((b >> 8) & 0xff); + c.b = (u8)((b >> 16) & 0xff); + c.a = (u8)((b >> 24) & 0xff); return c; }; v new_fb() { fb.data = malloc(W*H*sizeof(u32));} -void FB_set(int x, int y, C c) { (!fb.data || x<0 || y<0 || x>=W || y>=H) ? 0 : memcpy(fb.data + ((x + y * W)), &c, 4); } -C* FB_get(int x, int y) -{ - void* c = (!fb.data || x<0 || y<0 || x>=W || y>=H) ? (void*)0 : (void*)(new_C(fb.data[(x+y*W)])); - return (C*)c; -} +void FB_set(i32 x, i32 y, C c) { (!fb.data || x<0 || y<0 || x>=W || y>=H) ? 0 : memcpy(fb.data + ((x + y * W)), &c, 4); } + +//C* +//FB_get(i32 x, i32 y) +//{ +// void* c = (!fb.data || x<0 || y<0 || x>=W || y>=H) ? (void*)0 : (void*)(C_new(fb.data[(x+y*W)])); +// return (C*)c; +//} -void line(ivec2 v, ivec2 v1, C color) +void +line(ivec2 v, ivec2 v1, C color) { - int x,y,x0,x1,y0,y1,dx,dy,sx,sy,e,e2,p; + i32 x,y,x0,x1,y0,y1,dx,dy,sx,sy,e,e2,p; x0 = v.x; y0 = v.y; x1 = v1.x; @@ -145,16 +154,8 @@ init_sdl() { ren = SDL_CreateRenderer(win, -1, 0); } -//void -//drw_ls() -//{ -// line(0, 0, 256, 256, (C){0xff, 0xff, 0xff, 0xff}); -// line(23, 30,90, 50, (C){0xff, 0x0, 0x0, 255}); -// line(127,0, 0, 127, (C){0, 255, 0, 255}); -//} - -int -parse_obj(int *fcount, int *ecount) +i32 +parse_obj(i32 *fcount, i32 *ecount) { FILE *f; char *line; @@ -162,7 +163,7 @@ parse_obj(int *fcount, int *ecount) size_t len; ssize_t read; long pos; - int edge_count, face_count; + i32 edge_count, face_count; f = fopen("african.obj", "rb"); @@ -175,7 +176,7 @@ parse_obj(int *fcount, int *ecount) face_count = 0; while ((read = getline(&line, &len, f)) != -1) { - int i; + i32 i; i = 0; if (strstr(line, "v ") != NULL) { for ((p = strtok(line, " ")); p; (p = strtok(NULL, " "))) @@ -193,8 +194,8 @@ parse_obj(int *fcount, int *ecount) for ((p = strtok(line, " ")); p; (p = strtok(NULL, " "))) tokens[i++] = p; - faces = realloc(faces, (face_count + 1) * sizeof(int*)); - faces[face_count] = malloc(sizeof(int)*3); + faces = realloc(faces, (face_count + 1) * sizeof(i32*)); + faces[face_count] = malloc(sizeof(i32)*3); faces[face_count][0] = atoi(tokens[1]) - 1; faces[face_count][1] = atoi(tokens[2]) - 1; @@ -212,60 +213,66 @@ parse_obj(int *fcount, int *ecount) return 1; } + void -draw_obj(int fcount) +draw_obj(i32 fcount) { - for (int i=0; i<fcount-1; i++) { - int *face = faces[i]; + for (i32 i=0; i<fcount-1; i++) { + i32 *face = faces[i]; - for (int j=0; j<3; j++) { + for (i32 j=0; j<3; j++) { vec3f *v0 = vertices[face[j]]; vec3f *v1 = vertices[face[(j+1)%3]]; - int x0 = (v0->x+1.)*W/2.; - int y0 = W - ((v0->y+1.)*W/2.); - int x1 = (v1->x+1.)*W/2.; - int y1 = W - ((v1->y+1.)*W/2.); - line((ivec2){x0, y0}, (ivec2){x1, y1}, (C){0xff, 0xff, 0xff, 0xff}); + i32 x0 = (v0->x+1.)*W/2.; + i32 y0 = W - ((v0->y+1.)*W/2.); + i32 x1 = (v1->x+1.)*W/2.; + i32 y1 = W - ((v1->y+1.)*W/2.); + line((ivec2){x0, y0}, (ivec2){x1, y1}, C_new(0x3333ffff)); } } } -void triangle(ivec2 t0, ivec2 t1, ivec2 t2, C color) { - // sort the vertices, t0, t1, t2 lower−to−upper (bubblesort yay!) - ivec2 temp; - - if (t0.y>t1.y) VEC2I_SWAP(t0, t1); - if (t0.y>t2.y) VEC2I_SWAP(t0, t2); - if (t1.y>t2.y) VEC2I_SWAP(t1, t2); - int total_height = t2.y-t0.y; - for (int y=t0.y; y<=t1.y; y++) { - int segment_height = t1.y-t0.y+1; - int alpha = (y-t0.y)/total_height; - int beta = (y-t0.y)/segment_height; // be careful with divisions by zero - ivec2 A = IVEC2_op(t0,IVEC2_ops(IVEC2_op(t2,t0,SUB), alpha, MUL), ADD); - ivec2 B = IVEC2_op(t0,IVEC2_ops(IVEC2_op(t1,t0,SUB), beta, MUL), ADD); - if (A.x>B.x) VEC2I_SWAP(A, B); - for (int j=A.x; j<=B.x; j++) { - FB_set(j, y, color); // attention, due to int casts t0.y+i != A.y - } - } - - for (int y=t1.y; y<=t2.y; y++) { - int segment_height = t2.y-t1.y+1; - int alpha = (y-t0.y)/total_height; - int beta = (y-t1.y)/segment_height; // be careful with divisions by zero - ivec2 A = IVEC2_op(t0,IVEC2_ops(IVEC2_op(t2,t0,SUB), alpha, MUL), ADD); - ivec2 B = IVEC2_op(t1,IVEC2_ops(IVEC2_op(t1,t0,SUB), beta, MUL), ADD); - //ivec2 A = t0 + (t2-t0)*alpha; - //ivec2 B = t1 + (t2-t1)*beta; - if (A.x>B.x) VEC2I_SWAP(A, B); - for (int j=A.x; j<=B.x; j++) { - FB_set(j, y, color); // attention, due to int casts t0.y+i != A.y - } - } +void +triangle(ivec2 t0, ivec2 t1, ivec2 t2, C color) { + // sort the vertices, t0, t1, t2 lower−to−upper (bubblesort yay!) + ivec2 temp; + + if (t0.y>t1.y) VEC2I_SWAP(t0, t1); + if (t0.y>t2.y) VEC2I_SWAP(t0, t2); + if (t1.y>t2.y) VEC2I_SWAP(t1, t2); + + i32 total_height = t2.y - t0.y; + + for (i32 i = 0; i < total_height; i++) { + i32 second_half = i > (t1.y - t0.y) || t1.y == t0.y; + i32 segment_height = second_half ? t2.y - t1.y : t1.y - t0.y; + float alpha = (float)i / total_height; + float beta = (float)(i - (second_half ? t1.y - t0.y : 0)) / segment_height; // how far down are we + + ivec2 A = { + t0.x + (t2.x - t0.x) * alpha, + t0.y + i + }; + + ivec2 B = second_half ? + (ivec2){ + t1.x + (t2.x - t1.x) * beta, + t1.y + (i - (t1.y - t0.y)) + } : + (ivec2){ + t0.x + (t1.x - t0.x) * beta, + t0.y + i + }; + + if (A.x > B.x) VEC2I_SWAP(A, B); + // Draw horizontal span between A and B + for (i32 x = A.x; x <= B.x; x++) { + FB_set(x, A.y, color); + } + } } -int +i32 main() { init_sdl(); @@ -278,36 +285,41 @@ main() SDL_RenderClear(ren); - //int fcount, ecount; - //int ho = parse_obj(&fcount, &ecount); + //i32 fcount, ecount; + //i32 ho = parse_obj(&fcount, &ecount); //draw_obj(fcount); ivec2 t0[3] = {{10, 70}, {50, 160}, {70, 80}}; ivec2 t1[3] = {{180, 50}, {150, 1}, {70, 180}}; ivec2 t2[3] = {{180, 150}, {120, 160}, {130, 180}}; - triangle(t0[0], t0[1], t0[2], (C){0xff, 0x00, 0x00, 0xff}); - triangle(t1[0], t1[1], t1[2], (C){0xff, 0xff, 0xff, 0xff}); - triangle(t2[0], t2[1], t2[2], (C){0x00, 0xff, 0x00, 0xff}); + triangle(t0[0], t0[1], t0[2],C_new(0xff000000)); + triangle(t1[0], t1[1], t1[2],C_new(0xffff0000)); + triangle(t2[0], t2[1], t2[2],C_new(0x000ff000)); + //ivec2 v0 = {0, 0}; + //ivec2 v1 = {W, 0}; + //ivec2 v2 = {W/2, H}; + //triangle(v0, v1, v2,C_new(0xff000000)); - SDL_UpdateTexture(texture, NULL, fb.data, W * sizeof(Uint32)); + FB_flip_vert(fb.data); + + SDL_UpdateTexture(texture, NULL, fb.data, W * sizeof(u32)); SDL_RenderCopy(ren, texture, NULL, NULL); SDL_RenderPresent(ren); - while(1) { - SDL_Delay(33); - while(SDL_PollEvent(&ev) != 0) { - switch(ev.type) { - case SDL_QUIT: - SDL_Quit(); - exit(1); - } - switch(ev.key.keysym.sym) { - case SDLK_q: - SDL_Quit(); - exit(1); - } - } - } - return 0; + while(1) { + while(SDL_PollEvent(&ev) != 0) { + switch(ev.type) { + case SDL_QUIT: + SDL_Quit(); + exit(1); + } + switch(ev.key.keysym.sym) { + case SDLK_q: + SDL_Quit(); + exit(1); + } + } + } + return 0; }