# HG changeset patch # User Matti Hamalainen # Date 1349776975 -10800 # Node ID 3bff024a91bea07ba588ea937c3fe0136faf6bf0 # Parent 61b9cd67cd552f91855f66459ab59fe2f0753e56 Move 3D line/sprite renderer to separate module. diff -r 61b9cd67cd55 -r 3bff024a91be dmq3d.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmq3d.c Tue Oct 09 13:02:55 2012 +0300 @@ -0,0 +1,308 @@ +#include "dmq3d.h" +#include "dmimage.h" + + +#define DM_DRAWLINE_NAME dmDrawLineSpec +#define DM_DRAWLINE_DST_BYTES 4 +#define DM_DRAWLINE_DST_TYPE DMRGBA32 +#define DM_DRAWLINE_ARGS , SDL_Surface *bmp +#define DM_DRAWLINE_INIT const int px = bmp->w / 2, py = bmp->h / 2; +#define DM_DRAWLINE_INNER \ + dmUnscaledBlitSurface32to32Transparent(bmp, x0-px, y0-py, screen); +#define DM_DRAWLINE_SPEC +#include "dmdrawline.h" + + +static int dmFind3DBitmap(int nitems, DM3DBitmap *items, DM3DBitmap *item) +{ + int i; + for (i = 0; i < nitems; i++) + if (strcmp(item->name, items[i].name) == 0) + return i; + return -1; +} + +#define DM_FIND_ITEM_FUNC(NAME, TYPE) \ +static int dmFind3D ## NAME (int nitems, TYPE *items, TYPE *item) \ +{ \ + int i; \ + for (i = 0; i < nitems; i++) \ + if (memcmp(item, items+i, sizeof(TYPE)) == 0) \ + return i; \ + return -1; \ +} + +#define DM_ADD_ITEM_FUNC(NAME, TYPE) \ +static int dmAdd3D ## NAME (int *nitems, int *nalloc, TYPE **items, TYPE *item, int *res) \ +{ \ + int tmp; \ + if ((tmp = dmFind3D ## NAME (*nitems, *items, item)) >= 0) \ + { \ + if (res != NULL) *res = tmp; \ + return DMERR_OK; \ + } \ + if ((*nitems) + 1 >= *nalloc) \ + { \ + (*nalloc) += 16; \ + if ((*items = dmRealloc(*items, *nalloc * sizeof(TYPE))) == NULL) \ + return DMERR_MALLOC; \ + } \ + memcpy((*items) + (*nitems), item, sizeof(TYPE)); \ + if (res != NULL) *res = *nitems; \ + (*nitems)++; \ + return DMERR_OK; \ +} + +DM_FIND_ITEM_FUNC(Vertex, DMVector) +DM_FIND_ITEM_FUNC(Line, DM3DLine) +DM_FIND_ITEM_FUNC(Sprite, DM3DSprite) + +DM_ADD_ITEM_FUNC(Vertex, DMVector) +DM_ADD_ITEM_FUNC(Line, DM3DLine) +DM_ADD_ITEM_FUNC(Sprite, DM3DSprite) +DM_ADD_ITEM_FUNC(Bitmap, DM3DBitmap) + + +int dmAdd3DLineSpriteModelVertex(DM3DLineSpriteModel *model, DMVector *v, int *index) +{ + return dmAdd3DVertex(&model->nvertices, &model->nvertexalloc, + &model->vertices, v, index); +} + +int dmAdd3DLineSpriteModelLine(DM3DLineSpriteModel *model, DM3DLine *v, int *index) +{ + return dmAdd3DLine(&model->nlines, &model->nlinesalloc, + &model->lines, v, index); +} + +int dmAdd3DLineSpriteModelSprite(DM3DLineSpriteModel *model, DM3DSprite *v, int *index) +{ + return dmAdd3DSprite(&model->nsprites, &model->nspritesalloc, + &model->sprites, v, index); +} + +int dmAdd3DLineSpriteModelBitmap(DM3DLineSpriteModel *model, DM3DBitmap *v, int *index) +{ + return dmAdd3DBitmap(&model->nbitmaps, &model->nbitmapsalloc, + &model->bitmaps, v, index); +} + + +static inline DMFloat dmPX(DMVector p) +{ + return 320 + p.x * 250.0f / (p.z + 501.0f); +} + + +static inline DMFloat dmPY(DMVector p) +{ + return 200 + p.y * 250.0f / (p.z + 501.0f); +} + + +void dmDraw3DLineSpriteModel(SDL_Surface *screen, DM3DLineSpriteModel *model, DMVector *pos, DMMatrix *mat, SDL_Surface *fbmap, Uint32 lcol) +{ + int i; + for (i = 0; i < model->nlines; i++) + { + DM3DLine *line = &model->lines[i]; + DMVector pv[2]; + dm_vector_add_r(&pv[0], &model->vertices[line->v1], pos); + dm_vector_add_r(&pv[1], &model->vertices[line->v2], pos); + dm_vector_mul_by_mat_n(pv, 2, mat); + + if (line->type > 1) + dmDrawLineSpec(screen, dmPX(pv[0]), dmPY(pv[0]), dmPX(pv[1]), dmPY(pv[1]), lcol, fbmap); + else + dmDrawLine32(screen, dmPX(pv[0]), dmPY(pv[0]), dmPX(pv[1]), dmPY(pv[1]), lcol); + } + + for (i = 0; i < model->nsprites; i++) + { + DM3DSprite *sprite = &model->sprites[i]; + DM3DBitmap *bmp = &model->bitmaps[sprite->bitmap]; + DMVector pv, pt; + dm_vector_add_r(&pt, &model->vertices[sprite->v], pos); + dm_vector_mul_by_mat(&pv, &pt, mat); + dmUnscaledBlitSurface32to32Transparent(bmp->img, dmPX(pv), dmPY(pv), screen); + } +} + + +static char *dmSkipWhitespace(char *line, BOOL invert) +{ + if (invert) + for (; *line && !isspace(*line); line++); + else + for (; *line && isspace(*line); line++); + return line; +} + + +static char *dmSkipUntil(char *line, char ch) +{ + for (; *line && *line != ch; line++); + return line; +} + + +static BOOL dmReadCoordinate(char **line, float *value, BOOL next) +{ + *line = dmSkipWhitespace(*line, FALSE); + if (sscanf(*line, "%f", value) != 1) return FALSE; + if (next) + { + *line = dmSkipUntil(*line, ','); + if (**line != ',') return FALSE; + *(*line)++; + } + else + *line = dmSkipWhitespace(*line, TRUE); + + return TRUE; +} + +static BOOL dmReadLineSegments(char *line, DM3DLineSpriteModel *model) +{ + int nvertices, vertex, type; + int *indices = NULL; + if (sscanf(line+1, "%d", &nvertices) != 1) + { + dmError("No # of segments @ '%s'\n", line); + goto error; + } + + if ((indices = dmMalloc(sizeof(int) * (nvertices+1))) == NULL) + goto error; + + line = dmSkipWhitespace(line, TRUE); + for (vertex = 0; vertex <= nvertices; vertex++) + { + DMVector p; + if (!dmReadCoordinate(&line, &p.x, TRUE)) return FALSE; + if (!dmReadCoordinate(&line, &p.y, TRUE)) return FALSE; + if (!dmReadCoordinate(&line, &p.z, FALSE)) return FALSE; + if (dmAdd3DLineSpriteModelVertex(model, &p, &indices[vertex]) != DMERR_OK) + goto error; + line = dmSkipWhitespace(line, FALSE); + } + + if (sscanf(line, "%d", &type) != 1) + { + dmError("No line type @ '%s'\n", line); + goto error; + } + + for (vertex = 1; vertex <= nvertices; vertex++) + { + DM3DLine line; + line.v1 = indices[vertex - 1]; + line.v2 = indices[vertex]; + line.type = type; + if (dmAdd3DLineSpriteModelLine(model, &line, NULL) != DMERR_OK) + goto error; + } + + return TRUE; +error: + dmFree(indices); + return FALSE; +} + +static BOOL dmReadSprite(char *line, DM3DLineSpriteModel *model) +{ + DMVector pt; + DM3DSprite spr; + + line++; + if (!dmReadCoordinate(&line, &pt.x, TRUE)) return FALSE; + if (!dmReadCoordinate(&line, &pt.y, TRUE)) return FALSE; + if (!dmReadCoordinate(&line, &pt.z, FALSE)) return FALSE; + line = dmSkipWhitespace(line, FALSE); + if (*line != 'B') + { + dmError("No bitmap definition found for sprite.\n"); + return FALSE; + } + + spr.bitmap = atoi(line + 1); + + if (dmAdd3DLineSpriteModelVertex(model, &pt, &spr.v) != DMERR_OK) + return FALSE; + + if (dmAdd3DLineSpriteModelSprite(model, &spr, NULL) != DMERR_OK) + return FALSE; + + return TRUE; +} + +static BOOL dmReadBitmap(char *line, DM3DLineSpriteModel *model) +{ + DM3DBitmap bmp, *rbmp; + int index; + + strncpy(bmp.name, line + 1, sizeof(bmp.name)); + bmp.img = NULL; + + if (dmAdd3DLineSpriteModelBitmap(model, &bmp, &index) != DMERR_OK) + return FALSE; + + rbmp = &(model->bitmaps[index]); + if (rbmp->img == NULL) + { + DMResource *res = dmf_create_stdio(rbmp->name, "rb"); + if (res == NULL) + { + dmError("Could not open resource file '%s'.\n", rbmp->name); + return FALSE; + } + rbmp->img = dmLoadImage(res); + dmf_close(res); + if (rbmp->img == NULL) + { + dmError("Could not load image file '%s'.\n", rbmp->name); + return FALSE; + } + } + fprintf(stderr, "loaded '%s': %d: %p\n", rbmp->name, index, rbmp->img); + return TRUE; +} + + +int dmRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel *model) +{ + char line[512]; + + memset(model, 0, sizeof(*model)); + + while (dmfgets(line, sizeof(line), f) != NULL) + { + char *start = dmSkipWhitespace(line, FALSE); + switch (*start) + { + case 0: + case '#': + break; + + case 'B': + if (!dmReadBitmap(start, model)) + return DMERR_INVALID_DATA; + break; + + case 'L': + if (!dmReadLineSegments(start, model)) + return DMERR_INVALID_DATA; + break; + + case 'S': + if (!dmReadSprite(start, model)) + return DMERR_INVALID_DATA; + break; + + default: + break; + } + } + + return DMERR_OK; +} diff -r 61b9cd67cd55 -r 3bff024a91be dmq3d.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmq3d.h Tue Oct 09 13:02:55 2012 +0300 @@ -0,0 +1,67 @@ +/* + * DMLib + * -- Whatever + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + */ +#ifndef DMQ3D_H +#define DMQ3D_H + +#include "dmlib.h" +#include "dmvecmat.h" +#include "dmres.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct +{ + int v1, v2, type; +} DM3DLine; + + +typedef struct +{ + int v, bitmap; +} DM3DSprite; + + +typedef struct +{ + char name[64]; + SDL_Surface *img; +} DM3DBitmap; + + +typedef struct +{ + int nvertices, nvertexalloc; + DMVector *vertices; + + int nlines, nlinesalloc; + DM3DLine *lines; + + int nbitmaps, nbitmapsalloc; + DM3DBitmap *bitmaps; + + int nsprites, nspritesalloc; + DM3DSprite *sprites; +} DM3DLineSpriteModel; + + +int dmAdd3DLineSpriteModelVertex(DM3DLineSpriteModel *model, DMVector *v, int *index); +int dmAdd3DLineSpriteModelLine(DM3DLineSpriteModel *model, DM3DLine *v, int *index); +int dmAdd3DLineSpriteModelSprite(DM3DLineSpriteModel *model, DM3DSprite *v, int *index); +int dmAdd3DLineSpriteModelBitmap(DM3DLineSpriteModel *model, DM3DBitmap *v, int *index); + +int dmRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel *model); +void dmDraw3DLineSpriteModel(SDL_Surface *screen, DM3DLineSpriteModel *model, DMVector *pos, DMMatrix *mat, SDL_Surface *fbmap, Uint32 lcol); + + +#ifdef __cplusplus +} +#endif + +#endif // DMQ3D_H diff -r 61b9cd67cd55 -r 3bff024a91be vptest.c --- a/vptest.c Tue Oct 09 13:01:07 2012 +0300 +++ b/vptest.c Tue Oct 09 13:02:55 2012 +0300 @@ -1,9 +1,10 @@ #include "dmlib.h" #include "dmargs.h" -#include "dmvecmat.h" #include "dmres.h" #include "dmimage.h" #include "dmtext.h" +#include "dmq3d.h" +#include "dmvecmat.h" #include #define DM_COLORS (256) @@ -123,287 +124,6 @@ } -#define DM_DRAWLINE_NAME dmDrawLineSpec -#define DM_DRAWLINE_DST_BYTES 4 -#define DM_DRAWLINE_DST_TYPE DMRGBA32 -#define DM_DRAWLINE_ARGS , SDL_Surface *bmp -#define DM_DRAWLINE_INNER \ - dmUnscaledBlitSurface32to32Transparent(bmp, x0, y0, screen); -#define DM_DRAWLINE_SPEC -#include "dmdrawline.h" - - -typedef struct -{ - int v1, v2, type; -} DM3DLine; - -typedef struct -{ - int v, bitmap; -} DM3DSprite; - -typedef struct -{ - char name[64]; - SDL_Surface *img; -} DM3DBitmap; - -typedef struct -{ - int nvertices, nvertexalloc; - DMVector *vertices; - - int nlines, nlinesalloc; - DM3DLine *lines; - - int nbitmaps, nbitmapssalloc; - DM3DBitmap *bitmaps; - - int nsprites, nspritesalloc; - DM3DSprite *sprites; -} DM3DLineSpriteModel; - - -int dmFind3DSurface(int nitems, DM3DBitmap *items, DM3DBitmap *item) -{ - int i; - for (i = 0; i < nitems; i++) - if (strcmp(item->name, items[i].name) == 0) - return i; - return -1; -} - -#define DM_FIND_ITEM_FUNC(NAME, TYPE) \ -int dmFind3D ## NAME (int nitems, TYPE *items, TYPE *item) \ -{ \ - int i; \ - for (i = 0; i < nitems; i++) \ - if (memcmp(item, items+i, sizeof(TYPE)) == 0) \ - return i; \ - return -1; \ -} - -#define DM_ADD_ITEM_FUNC(NAME, TYPE) \ -int dmAdd3D ## NAME (int *nitems, int *nalloc, TYPE **items, TYPE *item, int *res) \ -{ \ - int tmp; \ - if ((tmp = dmFind3D ## NAME (*nitems, *items, item)) >= 0) \ - { \ - if (res != NULL) *res = tmp; \ - return DMERR_OK; \ - } \ - if ((*nitems) + 1 >= *nalloc) \ - { \ - (*nalloc) += 16; \ - if ((*items = dmRealloc(*items, *nalloc * sizeof(TYPE))) == NULL) \ - return DMERR_MALLOC; \ - } \ - memcpy((*items) + (*nitems), item, sizeof(TYPE)); \ - if (res != NULL) *res = *nitems; \ - (*nitems)++; \ - return DMERR_OK; \ -} - -DM_FIND_ITEM_FUNC(Vertex, DMVector) -DM_FIND_ITEM_FUNC(Line, DM3DLine) -DM_FIND_ITEM_FUNC(Sprite, DM3DSprite) - -DM_ADD_ITEM_FUNC(Vertex, DMVector) -DM_ADD_ITEM_FUNC(Line, DM3DLine) -DM_ADD_ITEM_FUNC(Sprite, DM3DSprite) -DM_ADD_ITEM_FUNC(Surface, DM3DBitmap) - -char *dmSkipWhitespace(char *line, BOOL invert) -{ - if (invert) - for (; *line && !isspace(*line); line++); - else - for (; *line && isspace(*line); line++); - return line; -} - -char *dmSkipUntil(char *line, char ch) -{ - for (; *line && *line != ch; line++); - return line; -} - -BOOL dmReadCoordinate(char **line, float *value, BOOL next) -{ - *line = dmSkipWhitespace(*line, FALSE); - if (sscanf(*line, "%f", value) != 1) return FALSE; - if (next) - { - *line = dmSkipUntil(*line, ','); - if (**line != ',') return FALSE; - *(*line)++; - } - else - *line = dmSkipWhitespace(*line, TRUE); - - return TRUE; -} - -BOOL dmReadLineSegments(char *line, DM3DLineSpriteModel *model) -{ - int nvertices, vertex, type; - int *indices = NULL; - if (sscanf(line+1, "%d", &nvertices) != 1) - { - dmError("No # of segments @ '%s'\n", line); - goto error; - } - - if ((indices = dmMalloc(sizeof(int) * (nvertices+1))) == NULL) - goto error; - - line = dmSkipWhitespace(line, TRUE); - for (vertex = 0; vertex <= nvertices; vertex++) - { - DMVector p; - if (!dmReadCoordinate(&line, &p.x, TRUE)) return FALSE; - if (!dmReadCoordinate(&line, &p.y, TRUE)) return FALSE; - if (!dmReadCoordinate(&line, &p.z, FALSE)) return FALSE; - if (dmAdd3DVertex(&model->nvertices, &model->nvertexalloc, - &model->vertices, &p, &indices[vertex]) != DMERR_OK) - goto error; - line = dmSkipWhitespace(line, FALSE); - } - - if (sscanf(line, "%d", &type) != 1) - { - dmError("No line type @ '%s'\n", line); - goto error; - } - - for (vertex = 1; vertex <= nvertices; vertex++) - { - DM3DLine line; - line.v1 = indices[vertex - 1]; - line.v2 = indices[vertex]; - line.type = type; - - if (dmAdd3DLine(&model->nlines, &model->nlinesalloc, - &model->lines, &line, NULL) != DMERR_OK) - goto error; - } - - return TRUE; -error: - dmFree(indices); - return FALSE; -} - -BOOL dmReadSprite(char *line, DM3DLineSpriteModel *model) -{ - DMVector pt; - DM3DSprite spr; - DM3DBitmap bmp, *rbmp; - - line++; - if (!dmReadCoordinate(&line, &pt.x, TRUE)) return FALSE; - if (!dmReadCoordinate(&line, &pt.y, TRUE)) return FALSE; - if (!dmReadCoordinate(&line, &pt.z, FALSE)) return FALSE; - line = dmSkipWhitespace(line, FALSE); - - if (dmAdd3DVertex(&model->nvertices, &model->nvertexalloc, - &model->vertices, &pt, &spr.v) != DMERR_OK) - return FALSE; - - strncpy(bmp.name, line, sizeof(bmp.name)); - bmp.img = NULL; - if (dmAdd3DSurface(&model->nbitmaps, &model->nbitmapssalloc, - &model->bitmaps, &bmp, &spr.bitmap) != DMERR_OK) - return FALSE; - - rbmp = &(model->bitmaps[spr.bitmap]); - if (rbmp->img == NULL) - { - DMResource *res = dmf_create_stdio(rbmp->name, "rb"); - if (res == NULL) - { - dmError("Could not open resource file '%s'.\n", rbmp->name); - return FALSE; - } - rbmp->img = dmLoadImage(res); - dmf_close(res); - if (rbmp->img == NULL) - { - dmError("Could not load image file '%s'.\n", rbmp->name); - return FALSE; - } - } - - if (dmAdd3DSprite(&model->nsprites, &model->nspritesalloc, - &model->sprites, &spr, NULL) != DMERR_OK) - return FALSE; - - return TRUE; -} - -int dmRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel *model) -{ - char line[512]; - - memset(model, 0, sizeof(*model)); - - while (dmfgets(line, sizeof(line), f) != NULL) - { - char *start = dmSkipWhitespace(line, FALSE); - switch (*start) - { - case 0: - case '#': - break; - - case 'L': - if (!dmReadLineSegments(start, model)) - return DMERR_INVALID_DATA; - break; - - case 'S': - if (!dmReadSprite(start, model)) - return DMERR_INVALID_DATA; - break; - - default: - printf("'%s'\n", start); - break; - } - } - - return DMERR_OK; -} - - -void dmDraw3DLineSpriteModel(SDL_Surface *screen, DM3DLineSpriteModel *model, DMVector pos, SDL_Surface *fbmap, Uint32 lcol) -{ - int i; - for (i = 0; i < model->nlines; i++) - { - DM3DLine *line = &model->lines[i]; - DMVector *v1 = &model->vertices[line->v1], - *v2 = &model->vertices[line->v2]; - if (line->type > 1) - dmDrawLineSpec(screen, pos.x + v1->x, pos.y + v1->y, pos.x + v2->x, pos.y + v2->y, lcol, fbmap); - else - dmDrawLine32(screen, pos.x + v1->x, pos.y + v1->y, pos.x + v2->x, pos.y + v2->y, lcol); - } - - for (i = 0; i < model->nsprites; i++) - { - DM3DSprite *sprite = &model->sprites[i]; - DM3DBitmap *bmp = &model->bitmaps[sprite->bitmap]; - DMVector *v = &model->vertices[sprite->v]; - - dmUnscaledBlitSurface32to32Transparent( - bmp->img, - pos.x + v->x, pos.y + v->y, screen); - } -} - - int main(int argc, char *argv[]) { SDL_Surface *screen = NULL, *bmap = NULL, *fbmap = NULL; @@ -568,21 +288,31 @@ qw2 = (float) 132.0 * (1.0 + sin(f) * 0.1), qh2 = (float) 132.0 * (1.0 + sin(f) * 0.1); +#if 1 dmScaledBlitSurfaceAny(bmap, bx-qw2, by-qh2, bmap->w+qw2, bmap->h+qh2, screen, // DMD_NONE - DMD_SATURATE + DMD_TRANSPARENT ); - +#endif +#if 0 + float qw = (float) 32.0 * (1.0 + sin(f) * 0.1), + qh = (float) 32.0 * (1.0 + sin(f) * 0.1), dmScaledBlitSurface32to32TransparentGA(bmap, bx*2-qw, by*2-qh, bmap->w+qw, bmap->h+qh, screen, 128 + sin(f*0.1) * 120.0f); - +#endif +#if 1 DMVector pos; - pos.x = 10; + pos.x = 40; pos.y = 10; pos.z = 0; - dmDraw3DLineSpriteModel(screen, &model, pos, fbmap, lcol); + DMMatrix mat; +// dm_matrix_rot_a(&mat, f*0.1, 0, (3.1415926535f * 2.0f * ((DMFloat) mouseX + (DMFloat) mouseY) ) / 500.0f); + dm_matrix_rot_a(&mat, 0, 0, f*0.1); + + dmDraw3DLineSpriteModel(screen, &model, &pos, &mat, fbmap, lcol); +#endif if (!optBenchmark)