Mercurial > hg > dmlib
view vptest.c @ 238:9643c517967d
Beginnings of a lines + sprites "3D" "model" renderer.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 09 Oct 2012 06:06:08 +0300 |
parents | 79dac918c81e |
children | 61b9cd67cd55 |
line wrap: on
line source
#include "dmlib.h" #include "dmargs.h" #include "dmvecmat.h" #include "dmres.h" #include "dmimage.h" #include "dmtext.h" #include <math.h> #define DM_COLORS (256) char *optFontFile = "font.ttf", *optBitmapFilename = "map.png"; BOOL optBenchmark = FALSE; int optVFlags = SDL_SWSURFACE | SDL_HWPALETTE; int optScrWidth = 640, optScrHeight = 480, optFontSize = 20, optScrDepth = 32; int optBenchmarkLen = 20; DMOptArg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 2, 'v', "verbose", "Be more verbose", OPT_NONE }, { 3, 'f', "full", "Fullscreen", OPT_NONE }, { 4, 'h', "hw", "Use SDL hardware surface", OPT_NONE }, { 5, 's', "size", "Initial window size/resolution -s 640x480", OPT_ARGREQ }, { 6, 'd', "depth", "Color depth of mode/window in bits (8/15/16/32)", OPT_ARGREQ }, { 7, 'b', "bench", "Run in benchmark mode", OPT_NONE }, }; const int optListN = sizeof(optList) / sizeof(optList[0]); void argShowHelp() { dmArgsPrintHelp(stdout, optList, optListN); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) { case 0: argShowHelp(); exit(0); break; case 2: dmVerbosity++; break; case 3: optVFlags |= SDL_FULLSCREEN; break; case 6: if (optArg) optScrDepth = atoi(optArg); break; case 5: { int w, h; if (sscanf(optArg, "%dx%d", &w, &h) == 2) { if (w < 320 || h < 200 || w > 3200 || h > 3200) { dmError("Invalid width or height: %d x %d\n", w, h); return FALSE; } optScrWidth = w; optScrHeight = h; } else { dmError("Invalid size argument '%s'.\n", optArg); return FALSE; } } break; case 7: optBenchmark = TRUE; break; default: dmError("Unknown option '%s'.\n", currArg); return FALSE; } return TRUE; } void DM_MakePalette(SDL_Surface *scr) { SDL_Color pal[DM_COLORS]; int n; for (n = 0; n < 256; n++) { pal[n].r = n; pal[n].g = n; pal[n].b = n; } SDL_SetColors(scr, pal, 0, DM_COLORS); } void DM_PrintRect(FILE *f, SDL_Rect *r) { fprintf(f, "SDL_Rect <%d, %d : %d, %d>\n", r->x, r->y, r->w, r->h); } BOOL DM_InitializeVideo(SDL_Surface **screen) { *screen = SDL_SetVideoMode(optScrWidth, optScrHeight, optScrDepth, optVFlags | SDL_RESIZABLE); if (*screen == NULL) { dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError()); return FALSE; } #if 0 SDL_Rect r; r.x = 50; r.y = 50; r.w = 320; r.h = 200; DM_PrintRect(stderr, &r); SDL_SetClipRect(*screen, &r); DM_PrintRect(stderr, &r); DM_PrintRect(stderr, &((*screen)->clip_rect)); #endif return TRUE; } #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; SDL_Color fontcol = { 255, 155, 155, 0 }; SDL_Event event; TTF_Font *font = NULL; int mouseX, mouseY, bx, by; BOOL initSDL = FALSE, initTTF = FALSE, exitFlag; DM3DLineSpriteModel model; dmVerbosity = 5; if (!dmArgsProcess(argc, argv, optList, optListN, argHandleOpt, NULL, FALSE)) exit(1); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { dmError("Could not initialize SDL: %s\n", SDL_GetError()); goto error_exit; } initSDL = TRUE; if (TTF_Init() < 0) { dmError("Could not initialize FreeType/TTF: %s\n", SDL_GetError()); goto error_exit; } initTTF = TRUE; font = TTF_OpenFont(optFontFile, optFontSize); if (font == NULL) { dmError("Could not load TTF font '%s' (%d): %s\n", optFontFile, optFontSize, SDL_GetError()); goto error_exit; } TTF_SetFontStyle(font, TTF_STYLE_NORMAL); DMResource *res = dmf_create_stdio(optBitmapFilename, "rb"); if (res == NULL) { dmError("Could not open resource file '%s'.\n", optBitmapFilename); goto error_exit; } bmap = dmLoadImage(res); dmf_close(res); if (bmap == NULL) { dmError("Could not load image file '%s'.\n", optBitmapFilename); goto error_exit; } res = dmf_create_stdio("trans6x6.png", "rb"); if (res == NULL) { dmError("Could not open resource file '%s'.\n", optBitmapFilename); goto error_exit; } fbmap = dmLoadImage(res); dmf_close(res); if (fbmap == NULL) { dmError("Could not load image file '%s'.\n", optBitmapFilename); goto error_exit; } res = dmf_create_stdio("mole.3d", "r"); if (res == NULL) { dmError("Could not open resource file '%s'.\n", optBitmapFilename); goto error_exit; } dmRead3DLineSpriteModel(res, &model); dmf_close(res); if (optBenchmark) { screen = SDL_CreateRGBSurface(SDL_SWSURFACE, optScrWidth, optScrHeight, optScrDepth, 0, 0, 0, 0); if (screen == NULL) { dmError("Could not create screen surface.\n"); goto error_exit; } dmMsg(0, "Benchmark mode, not opening window.\n"); } else { if (!DM_InitializeVideo(&screen)) goto error_exit; SDL_WM_SetCaption("Halleluja", "DMT"); } Uint32 lcol = dmMapRGB(screen, 255,255,255); int numFrames = 0, startTime = SDL_GetTicks(), endTime = 0; exitFlag = FALSE; if (optBenchmark) dmMsg(0, "Starting benchmark, running for %d seconds.\n", optBenchmarkLen); while (!exitFlag) { if (!optBenchmark) { while (SDL_PollEvent(&event)) switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: exitFlag = TRUE; break; default: break; } break; case SDL_VIDEORESIZE: optScrWidth = event.resize.w; optScrHeight = event.resize.h; if (!DM_InitializeVideo(&screen)) goto error_exit; break; case SDL_VIDEOEXPOSE: break; case SDL_QUIT: exit(0); } SDL_GetMouseState(&mouseX, &mouseY); bx = 300 - ((DMFloat) mouseX * 500.0f ) / (DMFloat) optScrWidth; by = 300 - ((DMFloat) mouseY * 500.0f ) / (DMFloat) optScrHeight; } else { bx = 0; by = 0; } if (!optBenchmark && SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0) { dmError("Can't lock surface.\n"); goto error_exit; } dmClearSurface(screen, 0); float f = SDL_GetTicks() / 150.0f, qw = (float) 32.0 * (1.0 + sin(f) * 0.1), qh = (float) 32.0 * (1.0 + sin(f) * 0.1), qw2 = (float) 132.0 * (1.0 + sin(f) * 0.1), qh2 = (float) 132.0 * (1.0 + sin(f) * 0.1); dmScaledBlitSurfaceAny(bmap, bx-qw2, by-qh2, bmap->w+qw2, bmap->h+qh2, screen, // DMD_NONE DMD_SATURATE ); dmScaledBlitSurface32to32TransparentGA(bmap, bx*2-qw, by*2-qh, bmap->w+qw, bmap->h+qh, screen, 128 + sin(f*0.1) * 120.0f); DMVector pos; pos.x = 10; pos.y = 10; pos.z = 0; dmDraw3DLineSpriteModel(screen, &model, pos, fbmap, lcol); if (!optBenchmark) { dmDrawTTFText(screen, font, fontcol, 0, 0, "%3.1f FPS", (float) (numFrames * 1000.0f) / (float) (endTime - startTime)); if (SDL_MUSTLOCK(screen) != 0) SDL_UnlockSurface(screen); SDL_Flip(screen); SDL_Delay(25); } endTime = SDL_GetTicks(); numFrames++; if (optBenchmark) { if (endTime - startTime > optBenchmarkLen * 1000) exitFlag = TRUE; } } // Print benchmark results dmMsg(0, "%d frames in %d ms, fps = %1.3f\n", numFrames, endTime - startTime, (float) (numFrames * 1000.0f) / (float) (endTime - startTime)); error_exit: dmMsg(0, "Shutting down dmlib.\n"); if (screen) SDL_FreeSurface(screen); if (bmap) SDL_FreeSurface(bmap); if (font) TTF_CloseFont(font); if (initSDL) SDL_Quit(); if (initTTF) TTF_Quit(); return 0; }