Basic 3D graphics for the MBED application-shield on-board LCD (initial/incomplete).

Dependents:   co657_lcdplay

gfx3d.cpp

Committer:
co657_frmb
Date:
2015-10-27
Revision:
2:f62652cae975
Parent:
1:f346d04ccbad
Child:
3:2d8982c06eee

File content as of revision 2:f62652cae975:

/*
 *  gfx3d.cpp -- 3D stuff for MBED (just playing!)
 *  Copyright (C) 2015 Fred Barnes, University of Kent  <frmb@kent.ac.uk>
 */

/** gfx3d library
 *
 *  This is a library for primitive 3D graphics.  No classes, just C functions.
 */
 

#include "mbed.h"
#include "C12832.h"
#include "gfx3d.h"


/** 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;
    }
    
}


/*
 *  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;
        }
    }
}


/*
 *  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 = (int)(ez * G3D_ZBSCALE) + G3D_ZBADD;
        ez += G3D_Z_DEPTH;
        dst[i].x = (int)((src[i].x / ez) * G3D_X_SCALE) + G3D_X2_SHIFT;
        dst[i].y = (int)((src[i].y / ez) * G3D_Y_SCALE) + G3D_Y2_SHIFT;
    }
}


/*
 *  takes a set of 8 projected points and draws a wireframe cube on the given LCD.  FIXME: only interested in the buffer ops..
 */
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);
}