From: falcovorbis <fal...@us...> - 2024-08-19 05:00:49
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via fff864a476bc3096afc0de1b515f1a4453a6caa5 (commit) from 9d115023ffc10996601a8e12fdb809cff2c5804f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit fff864a476bc3096afc0de1b515f1a4453a6caa5 Author: jnmartin84 <jnm...@gm...> Date: Mon Aug 19 00:55:22 2024 -0400 Add an example of how to render lines with the PVR. (#714) * Add PVR-accelerated line-rendering example. * turns out the endpoint order condition check is simple * cleanup vert swapping * formatting and comments * one missed spaces-to-tab * remove copyright header until I figure out what is wanted * fix remaining stray tab issues * update comments and long lines ----------------------------------------------------------------------- Summary of changes: examples/dreamcast/pvr/Makefile | 3 + .../{network/dns-client => pvr/pvrline}/Makefile | 7 +- examples/dreamcast/pvr/pvrline/pvrline.c | 264 +++++++++++++++++++++ 3 files changed, 271 insertions(+), 3 deletions(-) copy examples/dreamcast/{network/dns-client => pvr/pvrline}/Makefile (82%) create mode 100644 examples/dreamcast/pvr/pvrline/pvrline.c diff --git a/examples/dreamcast/pvr/Makefile b/examples/dreamcast/pvr/Makefile index 24812cfe..3cb67d66 100644 --- a/examples/dreamcast/pvr/Makefile +++ b/examples/dreamcast/pvr/Makefile @@ -6,6 +6,7 @@ all: $(KOS_MAKE) -C plasma + $(KOS_MAKE) -C pvrline $(KOS_MAKE) -C pvrmark $(KOS_MAKE) -C pvrmark_strips $(KOS_MAKE) -C pvrmark_strips_direct @@ -18,6 +19,7 @@ all: clean: $(KOS_MAKE) -C plasma clean + $(KOS_MAKE) -C pvrline clean $(KOS_MAKE) -C pvrmark clean $(KOS_MAKE) -C pvrmark_strips clean $(KOS_MAKE) -C pvrmark_strips_direct clean @@ -30,6 +32,7 @@ clean: dist: $(KOS_MAKE) -C plasma dist + $(KOS_MAKE) -C pvrline dist $(KOS_MAKE) -C pvrmark dist $(KOS_MAKE) -C pvrmark_strips dist $(KOS_MAKE) -C pvrmark_strips_direct dist diff --git a/examples/dreamcast/network/dns-client/Makefile b/examples/dreamcast/pvr/pvrline/Makefile similarity index 82% copy from examples/dreamcast/network/dns-client/Makefile copy to examples/dreamcast/pvr/pvrline/Makefile index 0e010c5a..a834749b 100644 --- a/examples/dreamcast/network/dns-client/Makefile +++ b/examples/dreamcast/pvr/pvrline/Makefile @@ -1,8 +1,8 @@ # Put the filename of the output binary here -TARGET = dns-client.elf +TARGET = pvrline.elf # List all of your C files here, but change the extension to ".o" -OBJS = dns-client.o +OBJS = pvrline.o all: rm-elf $(TARGET) @@ -18,8 +18,9 @@ $(TARGET): $(OBJS) kos-cc -o $(TARGET) $(OBJS) run: $(TARGET) - $(KOS_LOADER) $(TARGET) -n + $(KOS_LOADER) $(TARGET) dist: $(TARGET) -rm -f $(OBJS) $(KOS_STRIP) $(TARGET) + diff --git a/examples/dreamcast/pvr/pvrline/pvrline.c b/examples/dreamcast/pvr/pvrline/pvrline.c new file mode 100644 index 00000000..ee6632fb --- /dev/null +++ b/examples/dreamcast/pvr/pvrline/pvrline.c @@ -0,0 +1,264 @@ +/* + * KallistiOS ##version## + * + * examples/dreamcast/pvr/pvrline/pvrline.c + * Copyright (C) 2024 Jason Martin + * + * This example demonstrates the use of the PVR to draw lines with quads + * (as triangle strips). + * It also demonstrates the use of pvr_list_prim, interleaving the drawing of + * OPAQUE and TRANSPARENT polygons. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include <kos.h> + +/* 512 kb vertex buffer size */ +#define VERTBUF_SIZE (512*1024) + +KOS_INIT_FLAGS(INIT_DEFAULT); + +/* enable OP and TR lists */ +pvr_init_params_t pvr_params = { +{ PVR_BINSIZE_16, 0, PVR_BINSIZE_16, 0, 0 }, VERTBUF_SIZE, 1, 0, 0, 3 +}; + +uint8_t __attribute__((aligned(32))) op_buf[VERTBUF_SIZE]; +uint8_t __attribute__((aligned(32))) tr_buf[VERTBUF_SIZE]; + +/* + * given a vec3f_t representing the screen-space start of a line (x,y,z), + * a vec3f_t representing the screen-space end of a line (x,y,z), + * a color, a width, a pvr polygon list type and a pvr polygon header + * uses the PVR to draw a line with a triangle strip consisting of 4 vertices + * representing a quad +*/ +void draw_pvr_line(vec3f_t *v1, vec3f_t *v2, float width, int color, + int which_list, pvr_poly_hdr_t *which_hdr); + +int main(int argc, char **argv) +{ + pvr_poly_hdr_t op_hdr, tr_hdr; + pvr_poly_cxt_t op_cxt, tr_cxt; + + /* start and end points of a line in screen-space */ + vec3f_t v1, v2; + /* red, green, blue and alpha color components */ + int r, g, b, a; + /* packed color */ + int color; + /* line width */ + int width; + /* moving offset added or subtracted to x and y components of endpoints */ + int offset; + /* number of lines to draw per frame */ + int linecount = 1; + + maple_device_t *controller; + cont_state_t *cont; + + printf("---KallistiOS PVR Line-drawing Example---\n"); + printf("Press DPAD UP to increase line count\n\t(up to a maximum of 1536" + " lines).\n"); + printf("Press DPAD DOWN to decrease line count\n\t(down to a minimum of 1" + " line).\n"); + printf("Press A to reset line count to 1.\n"); + printf("Press Start to exit.\n"); + + srand(time(NULL)); + + vid_set_enabled(0); + vid_set_mode(DM_640x480, PM_RGB565); + pvr_init(&pvr_params); + vid_set_enabled(1); + + /* polygon header setup, OP lines */ + pvr_poly_cxt_col(&op_cxt, PVR_LIST_OP_POLY); + pvr_poly_compile(&op_hdr, &op_cxt); + + /* polygon header setup, TR lines */ + pvr_poly_cxt_col(&tr_cxt, PVR_LIST_TR_POLY); + pvr_poly_compile(&tr_hdr, &tr_cxt); + + offset = 0; + + while (true) { + controller = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + if (controller) { + cont = maple_dev_status(controller); + if (cont->buttons & CONT_DPAD_UP) { + if (linecount < 1536) { + linecount += 1; + } + } else if (cont->buttons & CONT_DPAD_DOWN) { + if (linecount > 1) { + linecount -= 1; + } + } else if (cont->buttons & CONT_A) { + linecount = 1; + } else if (cont->buttons & CONT_START) { + break; + } + } + + pvr_wait_ready(); + pvr_scene_begin(); + + /* set vertex buffers for pvr_list_prim use */ + pvr_set_vertbuf(PVR_LIST_OP_POLY, op_buf, VERTBUF_SIZE); + pvr_set_vertbuf(PVR_LIST_TR_POLY, tr_buf, VERTBUF_SIZE); + + /* + * incrementing offset added to endpoints + * make endpoints occasionally move to other side of screen + * from where they start + * force swaps in the line drawing routine + */ + offset = (offset + 5) % 360; + + for (int i = 0; i < linecount; i++) { + v1.x = rand() % 128; + v1.y = rand() % 64; + v1.z = 5; + + v2.x = 500 + (rand() % 96); + v2.y = 400 + (rand() % 48); + v2.z = 5; + + /* + * add an offset in the range [0,359] to v1 x and y + * x stays within [0,487] + * y stays within [0,422] + */ + v1.x += offset; + v1.y += offset; + + /* + * subtract an offset in the range [0,359] from v2 x and y + * x stays within [141,595] + * y stays within [40,447] + */ + v2.x -= offset; + v2.y -= offset; + + /* + * the above offset can move v2 to the left of v1 + * this demonstrates that lines will always render correctly + * regardless of vertex order + */ + + /* generate a random RGBA color */ + r = rand() % 256; + g = rand() % 256; + b = rand() % 256; + a = rand() % 256; + + color = PVR_PACK_COLOR((float)a / 255.0f, + (float)r / 255.0f, + (float)g / 255.0f, + (float)b / 255.0f); + + width = (rand() % 5) + 1; + + /* interleaved use of PVR polygon list types */ + if (a == 255) { + /* + * when alpha is fully opaque + * use the OP list + */ + draw_pvr_line(&v1, &v2, width, color, + PVR_LIST_OP_POLY, &op_hdr); + } else { + /* + * when alpha is transparent at all + * use the TR list + */ + draw_pvr_line(&v1, &v2, width, color, + PVR_LIST_TR_POLY, &tr_hdr); + } + } + + pvr_scene_finish(); + } +} + +void draw_pvr_line(vec3f_t *v1, vec3f_t *v2, float width, int color, + int which_list, pvr_poly_hdr_t *which_hdr) +{ + pvr_vertex_t __attribute__((aligned(32))) line_verts[4]; + pvr_vertex_t *vert = line_verts; + + vec3f_t *ov1; + vec3f_t *ov2; + + for (int i=0;i<4;i++) { + line_verts[i].flags = PVR_CMD_VERTEX; + line_verts[i].argb = color; + line_verts[i].oargb = 0; + } + line_verts[3].flags = PVR_CMD_VERTEX_EOL; + + /* + * when first vertex is to the left of or vertical with second vertex + * they are already ordered + * otherwise + * swap endpoints + */ + if(v1->x <= v2->x) { + ov1 = v1; + ov2 = v2; + } else { + ov1 = v2; + ov2 = v1; + } + + /* + * https://devcry.heiho.net/html/2017/20170820-opengl-line-drawing.html + * + * get the normal to the line segment running from v1 to v2 + * use normal to draw a quad covering the actual line segment + */ + float dx = ov2->x - ov1->x; + float dy = ov2->y - ov1->y; + + /* + * use the fast reciprocal square root function provided by KOS + * to get inverse of the magnitude of the normal + * multiply by half of the line width + * this scales the normal, making a quad with the requested line width + */ + float inverse_magnitude = frsqrt((dx*dx) + (dy*dy)) * + ((float)width*0.5f); + float nx = -dy * inverse_magnitude; + float ny = dx * inverse_magnitude; + + /* normal offset "down" from the first endpoint */ + vert->x = ov1->x + nx; + vert->y = ov1->y + ny; + vert->z = ov1->z; + vert++; + + /* normal offset "up" from the first endpoint */ + vert->x = ov1->x - nx; + vert->y = ov1->y - ny; + vert->z = ov2->z; + vert++; + + /* normal offset "down" from the second endpoint */ + vert->x = ov2->x + nx; + vert->y = ov2->y + ny; + vert->z = ov1->z; + vert++; + + /* normal offset "up" from the second endpoint */ + vert->x = ov2->x - nx; + vert->y = ov2->y - ny; + vert->z = ov2->z; + + /* submit the poly header and vertices to requested list */ + pvr_list_prim(which_list, which_hdr, sizeof(pvr_poly_hdr_t)); + pvr_list_prim(which_list, &line_verts, 4 * sizeof(pvr_vertex_t)); +} hooks/post-receive -- A pseudo Operating System for the Dreamcast. |