Mercurial > hg > dmlib
view dmq3d.c @ 256:31ce6d32408f
Error out when bezier segments are found.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 09 Oct 2012 23:44:02 +0300 |
parents | 61eb5fb4a5e6 |
children | be2ca95af493 |
line wrap: on
line source
#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(int cx, DMVector p) { return cx + (p.x * 250.0f) / p.z; } static inline DMFloat dmPY(int cy, DMVector p) { return cy + (p.y * 250.0f) / p.z; } void dmDraw3DLineSpriteModel(SDL_Surface *screen, DM3DLineSpriteModel *model, DMVector *pos, DMMatrix *mat, SDL_Surface *fbmap, Uint32 lcol) { int i; int cx = screen->w / 2, cy = screen->h / 2; for (i = 0; i < model->nlines; i++) { DM3DLine *line = &model->lines[i]; DMVector pv[2]; dm_vector_copy(&pv[0], &model->vertices[line->v1]); dm_vector_copy(&pv[1], &model->vertices[line->v2]); dm_vector_mul_by_mat_n(pv, 2, mat); dm_vector_add(&pv[0], pos); dm_vector_add(&pv[1], pos); if (line->type > 1) dmDrawLineSpec(screen, dmPX(cx, pv[0]), dmPY(cy, pv[0]), dmPX(cx, pv[1]), dmPY(cy, pv[1]), lcol, fbmap); else dmDrawLine32(screen, dmPX(cx, pv[0]), dmPY(cy, pv[0]), dmPX(cx, pv[1]), dmPY(cy, pv[1]), lcol); } for (i = 0; i < model->nsprites; i++) { DM3DSprite *sprite = &model->sprites[i]; DM3DBitmap *bmp = &model->bitmaps[sprite->bitmap]; DMVector pv; dm_vector_mul_by_mat(&pv, &model->vertices[sprite->v], mat); dm_vector_add(&pv, pos); dmUnscaledBlitSurface32to32Transparent(bmp->img, dmPX(cx, pv), dmPY(cy, 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, BOOL relative, const DMVector *pt) { 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); DMVector v, p, *t; dm_vector_copy(&v, pt); for (vertex = 0; vertex <= nvertices; vertex++) { if (*line == 'Z') { indices[vertex] = indices[0]; line++; } else { 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 (relative) { dm_vector_add(&v, &p); t = &v; } else { dm_vector_add_r(&v, &p, pt); t = &v; } if (dmAdd3DLineSpriteModelVertex(model, t, &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 *pos) { 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); dm_vector_add(&pt, pos); 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; } static int dmDoRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel *model, DMVector *pos) { char line[512]; while (dmfgets(line, sizeof(line), f) != NULL) { char *start = dmSkipWhitespace(line, FALSE); switch (*start) { case 0: case '#': break; case 'G': { int res; DMVector pt; start++; if (!dmReadCoordinate(&start, &pt.x, TRUE)) return DMERR_INVALID_DATA; if (!dmReadCoordinate(&start, &pt.y, TRUE)) return DMERR_INVALID_DATA; if (!dmReadCoordinate(&start, &pt.z, FALSE)) return DMERR_INVALID_DATA; dm_vector_add_r(&pt, pos, &pt); if ((res = dmDoRead3DLineSpriteModel(f, model, &pt)) != DMERR_OK) return res; } break; case 'E': return DMERR_OK; case 'B': if (!dmReadBitmap(start, model)) return DMERR_INVALID_DATA; break; case 'L': if (!dmReadLineSegments(start, model, FALSE, pos)) return DMERR_INVALID_DATA; break; case 'R': if (!dmReadLineSegments(start, model, TRUE, pos)) return DMERR_INVALID_DATA; break; case 'S': if (!dmReadSprite(start, model, pos)) return DMERR_INVALID_DATA; break; default: break; } } return DMERR_OK; } int dmRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel **model) { DMVector pos; if ((*model = dmMalloc0(sizeof(DM3DLineSpriteModel))) == NULL) return DMERR_MALLOC; memset(&pos, 0, sizeof(pos)); return dmDoRead3DLineSpriteModel(f, *model, &pos); } void dmFree3DLineSpriteModel(DM3DLineSpriteModel *model) { int i; for (i = 0; i < model->nbitmaps; i++) { if (model->bitmaps[i].img != NULL) SDL_FreeSurface(model->bitmaps[i].img); } dmFree(model->bitmaps); dmFree(model->vertices); dmFree(model->lines); dmFree(model->sprites); dmFree(model); }