Basic 3D graphics for the MBED application-shield on-board LCD (initial/incomplete).
gfx3d.cpp
- Committer:
- co657_frmb
- Date:
- 2015-11-28
- Revision:
- 8:55ee7af49f47
- Parent:
- 6:0bd002c936bb
File content as of revision 8:55ee7af49f47:
/* * gfx3d.cpp -- 3D stuff for MBED (just playing!) * Copyright (C) 2015 Fred Barnes, University of Kent <frmb@kent.ac.uk> */ #include "mbed.h" #include "C12832.h" #include "gfx3d.h" #define DISPLAY_WIDTH (128) #define DISPLAY_HEIGHT (32) static float g3d_z_depth = G3D_Z_DEPTH; static float g3d_x_scale = G3D_X_SCALE; static float g3d_y_scale = G3D_Y_SCALE; /** Sets the Z depth */ void gfx3d_set_z_depth (const float zd) { g3d_z_depth = zd; } /** rotates a base set of points into a new set (demoscene style) * * @param src Source points. * @param dst Destination points. * @param npnts Number of points. * @param a Angle to rotate by (0-255). */ void gfx3d_rotate_demo (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const angle_t a) { float sinval = gfx3d_sin (a); float cosval = gfx3d_cos (a); int i; for (i=0; i<npnts; i++) { float x1 = (src[i].x * cosval) + (src[i].y * sinval); float y1 = (src[i].y * cosval) - (src[i].x * sinval); float z1 = (src[i].z * cosval) - (x1 * sinval); float t; dst[i].x = (x1 * cosval) + (src[i].z * sinval); t = (y1 * cosval) + (z1 * sinval); dst[i].z = (z1 * cosval) - (y1 * sinval); dst[i].y = t; } } /** rotates a set of points around the X axis. * * @param src Source points. * @param dst Destination points. * @param npnts Number of points. * @param a Angle to rotate by (0-255). */ void gfx3d_rotate_x (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const angle_t a) { float sinval = gfx3d_sin (a); float cosval = gfx3d_cos (a); int i; for (i=0; i<npnts; i++) { float t = src[i].y; dst[i].x = src[i].x; dst[i].y = (src[i].y * cosval) + (src[i].z * sinval); dst[i].z = (src[i].z * cosval) - (t * sinval); } } void gfx3d_rotate_y (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const angle_t a) { float sinval = gfx3d_sin (a); float cosval = gfx3d_cos (a); int i; for (i=0; i<npnts; i++) { float t = src[i].x; dst[i].x = (src[i].x * cosval) + (src[i].z * sinval); dst[i].y = src[i].y; dst[i].z = (src[i].z * cosval) - (t * sinval); } } void gfx3d_rotate_z (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const angle_t a) { float sinval = gfx3d_sin (a); float cosval = gfx3d_cos (a); int i; for (i=0; i<npnts; i++) { float t = src[i].x; dst[i].x = (src[i].x * cosval) + (src[i].y * sinval); dst[i].y = (src[i].y * cosval) - (t * sinval); dst[i].z = src[i].z; } } /* * translates a set of 3D points. 'src' and 'dst' can be the same */ void gfx3d_translate (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const g3d_p3_t tx) { int i; if (tx.x != 0.0f) { for (i=0; i<npnts; i++) { dst[i].x = src[i].x + tx.x; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].x = src[i].x; } } if (tx.y != 0.0f) { for (i=0; i<npnts; i++) { dst[i].y = src[i].y + tx.y; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].y = src[i].y; } } if (tx.z != 0.0f) { for (i=0; i<npnts; i++) { dst[i].z = src[i].z + tx.z; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].z = src[i].z; } } } /** Scales a set of points. * */ void gfx3d_scale (const g3d_p3_t *src, g3d_p3_t *dst, const int npnts, const g3d_p3_t scl) { int i; if (scl.x != 1.0f) { for (i=0; i<npnts; i++) { dst[i].x = src[i].x * scl.x; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].x = src[i].x; } } if (scl.y != 1.0f) { for (i=0; i<npnts; i++) { dst[i].y = src[i].y * scl.y; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].y = src[i].y; } } if (scl.z != 1.0f) { for (i=0; i<npnts; i++) { dst[i].z = src[i].z * scl.z; } } else if (src != dst) { for (i=0; i<npnts; i++) { dst[i].z = src[i].z; } } } /** * projects a set of 3D points into a 2D space (pretty crude) */ void gfx3d_project (const g3d_p3_t *src, g3d_2p3_t *dst, const int npnts) { int i; for (i=0; i<npnts; i++) { float ez = src[i].z; dst[i].z = (int16_t)((ez + G3D_ZBADD) * G3D_ZBSCALE); ez += g3d_z_depth; dst[i].x = (int16_t)((src[i].x * g3d_x_scale) / ez) + G3D_X2_SHIFT; dst[i].y = (int16_t)((src[i].y * g3d_y_scale) / ez) + G3D_Y2_SHIFT; } } /** Takes a set of 8 projected points and creates a set of <=12 triangular polygons representing the surface of a cube. * Also attaches texture pointers if given. */ void gfx3d_cubify_points (const g3d_2p3_t *src, g3d_poly_t *dst, int *npoly, const int backfaces, const uint8_t **txptrs) { static const int cubemap3[12][3] = {{3,0,1}, {1,2,3}, {2,1,5}, {5,6,2}, {6,5,4}, {4,7,6}, {7,4,0}, {0,3,7}, {1,0,4}, {4,5,1}, {7,3,2}, {2,6,7}}; static const uint16_t txmap[2][3] = {{0x1f00, 0x0000, 0x001f}, {0x001f, 0x1f1f, 0x1f00}}; /* 0xYYXX */ int i, pidx; int norms[6]; *npoly = 12; /* assume all to start with */ /* compute normals */ for (i=0; i<6; i++) { const int *face = cubemap3[i*2]; int norm = ((src[face[0]].y - src[face[1]].y) * (src[face[2]].x - src[face[1]].x)) - ((src[face[2]].y - src[face[1]].y) * (src[face[0]].x - src[face[1]].x)); if (!backfaces && (norm < 0)) { /* not showing this one */ *npoly = *npoly - 2; } norms[i] = norm; } /* wind polygons */ pidx = 0; for (i=0; (i<12) && (pidx < *npoly); i++) { if (!backfaces && (norms[i>>1] < 0)) { /* not showing this one */ } else { int p; dst[pidx].norm = norms[i>>1]; dst[pidx].txptr = (txptrs == NULL) ? NULL : (uint8_t *)txptrs[i>>1]; for (p=0; p<3; p++) { dst[pidx].pts[p].x = src[cubemap3[i][p]].x; dst[pidx].pts[p].y = src[cubemap3[i][p]].y; dst[pidx].pts[p].z = src[cubemap3[i][p]].z; dst[pidx].tx_pts[p] = txmap[i&1][p]; } pidx++; } } } /** * takes a set of 4 projected points and creates a set of <=2 triangular polygons representing the square */ void gfx3d_squarify_points (const g3d_2p3_t *src, g3d_poly_t *dst, int *npoly, const int backfaces) { static const int squaremap3[2][3] = {{3,0,1}, {1,2,3}}; static const uint16_t txmap[2][3] = {{0x1f00, 0x0000, 0x001f}, {0x001f, 0x1f1f, 0x1f00}}; /* 0xYYXX */ int i, pidx; int norm = ((src[3].y - src[0].y) * (src[1].x - src[0].x)) - ((src[1].y - src[0].y) * (src[3].x - src[0].x)); if (!backfaces && (norm < 0)) { /* not showing anything */ *npoly = 0; return; } *npoly = 2; /* wind polygons */ for (i=0; i<2; i++) { int p; dst[i].norm = norm; for (p=0; p<3; p++) { dst[i].pts[p].x = src[squaremap3[i][p]].x; dst[i].pts[p].y = src[squaremap3[i][p]].y; dst[i].pts[p].z = src[squaremap3[i][p]].z; dst[i].tx_pts[p] = txmap[i][p]; } } return; } /** * takes a polygon and draws its wireframe on the given LCD. */ void gfx3d_wirepoly (const g3d_poly_t *src, C12832 &lcd) { #if G3D_MAX_POLY_POINTS == 3 lcd.line (src->pts[0].x, src->pts[0].y, src->pts[1].x, src->pts[1].y, 1); lcd.line (src->pts[1].x, src->pts[1].y, src->pts[2].x, src->pts[2].y, 1); lcd.line (src->pts[2].x, src->pts[2].y, src->pts[0].x, src->pts[0].y, 1); #endif } /** * takes a polygon and draws its wireframe on the given LCD, taking Z buffering into consideration */ void gfx3d_wirepoly_z (const g3d_poly_t *src, C12832 &lcd) { #if G3D_MAX_POLY_POINTS == 3 #endif } /** * takes a set of 8 projected points and draws a wireframe cube on the given LCD. */ void gfx3d_wirecube (const g3d_2p3_t *src, C12832 &lcd) { lcd.line (src[0].x, src[0].y, src[1].x, src[1].y, 1); lcd.line (src[1].x, src[1].y, src[2].x, src[2].y, 1); lcd.line (src[2].x, src[2].y, src[3].x, src[3].y, 1); lcd.line (src[3].x, src[3].y, src[0].x, src[0].y, 1); lcd.line (src[4].x, src[4].y, src[5].x, src[5].y, 1); lcd.line (src[5].x, src[5].y, src[6].x, src[6].y, 1); lcd.line (src[6].x, src[6].y, src[7].x, src[7].y, 1); lcd.line (src[7].x, src[7].y, src[4].x, src[4].y, 1); lcd.line (src[0].x, src[0].y, src[4].x, src[4].y, 1); lcd.line (src[1].x, src[1].y, src[5].x, src[5].y, 1); lcd.line (src[2].x, src[2].y, src[6].x, src[6].y, 1); lcd.line (src[3].x, src[3].y, src[7].x, src[7].y, 1); }