comparison dmq3d.c @ 241:3bff024a91be

Move 3D line/sprite renderer to separate module.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 09 Oct 2012 13:02:55 +0300
parents
children a9d500e5698d
comparison
equal deleted inserted replaced
240:61b9cd67cd55 241:3bff024a91be
1 #include "dmq3d.h"
2 #include "dmimage.h"
3
4
5 #define DM_DRAWLINE_NAME dmDrawLineSpec
6 #define DM_DRAWLINE_DST_BYTES 4
7 #define DM_DRAWLINE_DST_TYPE DMRGBA32
8 #define DM_DRAWLINE_ARGS , SDL_Surface *bmp
9 #define DM_DRAWLINE_INIT const int px = bmp->w / 2, py = bmp->h / 2;
10 #define DM_DRAWLINE_INNER \
11 dmUnscaledBlitSurface32to32Transparent(bmp, x0-px, y0-py, screen);
12 #define DM_DRAWLINE_SPEC
13 #include "dmdrawline.h"
14
15
16 static int dmFind3DBitmap(int nitems, DM3DBitmap *items, DM3DBitmap *item)
17 {
18 int i;
19 for (i = 0; i < nitems; i++)
20 if (strcmp(item->name, items[i].name) == 0)
21 return i;
22 return -1;
23 }
24
25 #define DM_FIND_ITEM_FUNC(NAME, TYPE) \
26 static int dmFind3D ## NAME (int nitems, TYPE *items, TYPE *item) \
27 { \
28 int i; \
29 for (i = 0; i < nitems; i++) \
30 if (memcmp(item, items+i, sizeof(TYPE)) == 0) \
31 return i; \
32 return -1; \
33 }
34
35 #define DM_ADD_ITEM_FUNC(NAME, TYPE) \
36 static int dmAdd3D ## NAME (int *nitems, int *nalloc, TYPE **items, TYPE *item, int *res) \
37 { \
38 int tmp; \
39 if ((tmp = dmFind3D ## NAME (*nitems, *items, item)) >= 0) \
40 { \
41 if (res != NULL) *res = tmp; \
42 return DMERR_OK; \
43 } \
44 if ((*nitems) + 1 >= *nalloc) \
45 { \
46 (*nalloc) += 16; \
47 if ((*items = dmRealloc(*items, *nalloc * sizeof(TYPE))) == NULL) \
48 return DMERR_MALLOC; \
49 } \
50 memcpy((*items) + (*nitems), item, sizeof(TYPE)); \
51 if (res != NULL) *res = *nitems; \
52 (*nitems)++; \
53 return DMERR_OK; \
54 }
55
56 DM_FIND_ITEM_FUNC(Vertex, DMVector)
57 DM_FIND_ITEM_FUNC(Line, DM3DLine)
58 DM_FIND_ITEM_FUNC(Sprite, DM3DSprite)
59
60 DM_ADD_ITEM_FUNC(Vertex, DMVector)
61 DM_ADD_ITEM_FUNC(Line, DM3DLine)
62 DM_ADD_ITEM_FUNC(Sprite, DM3DSprite)
63 DM_ADD_ITEM_FUNC(Bitmap, DM3DBitmap)
64
65
66 int dmAdd3DLineSpriteModelVertex(DM3DLineSpriteModel *model, DMVector *v, int *index)
67 {
68 return dmAdd3DVertex(&model->nvertices, &model->nvertexalloc,
69 &model->vertices, v, index);
70 }
71
72 int dmAdd3DLineSpriteModelLine(DM3DLineSpriteModel *model, DM3DLine *v, int *index)
73 {
74 return dmAdd3DLine(&model->nlines, &model->nlinesalloc,
75 &model->lines, v, index);
76 }
77
78 int dmAdd3DLineSpriteModelSprite(DM3DLineSpriteModel *model, DM3DSprite *v, int *index)
79 {
80 return dmAdd3DSprite(&model->nsprites, &model->nspritesalloc,
81 &model->sprites, v, index);
82 }
83
84 int dmAdd3DLineSpriteModelBitmap(DM3DLineSpriteModel *model, DM3DBitmap *v, int *index)
85 {
86 return dmAdd3DBitmap(&model->nbitmaps, &model->nbitmapsalloc,
87 &model->bitmaps, v, index);
88 }
89
90
91 static inline DMFloat dmPX(DMVector p)
92 {
93 return 320 + p.x * 250.0f / (p.z + 501.0f);
94 }
95
96
97 static inline DMFloat dmPY(DMVector p)
98 {
99 return 200 + p.y * 250.0f / (p.z + 501.0f);
100 }
101
102
103 void dmDraw3DLineSpriteModel(SDL_Surface *screen, DM3DLineSpriteModel *model, DMVector *pos, DMMatrix *mat, SDL_Surface *fbmap, Uint32 lcol)
104 {
105 int i;
106 for (i = 0; i < model->nlines; i++)
107 {
108 DM3DLine *line = &model->lines[i];
109 DMVector pv[2];
110 dm_vector_add_r(&pv[0], &model->vertices[line->v1], pos);
111 dm_vector_add_r(&pv[1], &model->vertices[line->v2], pos);
112 dm_vector_mul_by_mat_n(pv, 2, mat);
113
114 if (line->type > 1)
115 dmDrawLineSpec(screen, dmPX(pv[0]), dmPY(pv[0]), dmPX(pv[1]), dmPY(pv[1]), lcol, fbmap);
116 else
117 dmDrawLine32(screen, dmPX(pv[0]), dmPY(pv[0]), dmPX(pv[1]), dmPY(pv[1]), lcol);
118 }
119
120 for (i = 0; i < model->nsprites; i++)
121 {
122 DM3DSprite *sprite = &model->sprites[i];
123 DM3DBitmap *bmp = &model->bitmaps[sprite->bitmap];
124 DMVector pv, pt;
125 dm_vector_add_r(&pt, &model->vertices[sprite->v], pos);
126 dm_vector_mul_by_mat(&pv, &pt, mat);
127 dmUnscaledBlitSurface32to32Transparent(bmp->img, dmPX(pv), dmPY(pv), screen);
128 }
129 }
130
131
132 static char *dmSkipWhitespace(char *line, BOOL invert)
133 {
134 if (invert)
135 for (; *line && !isspace(*line); line++);
136 else
137 for (; *line && isspace(*line); line++);
138 return line;
139 }
140
141
142 static char *dmSkipUntil(char *line, char ch)
143 {
144 for (; *line && *line != ch; line++);
145 return line;
146 }
147
148
149 static BOOL dmReadCoordinate(char **line, float *value, BOOL next)
150 {
151 *line = dmSkipWhitespace(*line, FALSE);
152 if (sscanf(*line, "%f", value) != 1) return FALSE;
153 if (next)
154 {
155 *line = dmSkipUntil(*line, ',');
156 if (**line != ',') return FALSE;
157 *(*line)++;
158 }
159 else
160 *line = dmSkipWhitespace(*line, TRUE);
161
162 return TRUE;
163 }
164
165 static BOOL dmReadLineSegments(char *line, DM3DLineSpriteModel *model)
166 {
167 int nvertices, vertex, type;
168 int *indices = NULL;
169 if (sscanf(line+1, "%d", &nvertices) != 1)
170 {
171 dmError("No # of segments @ '%s'\n", line);
172 goto error;
173 }
174
175 if ((indices = dmMalloc(sizeof(int) * (nvertices+1))) == NULL)
176 goto error;
177
178 line = dmSkipWhitespace(line, TRUE);
179 for (vertex = 0; vertex <= nvertices; vertex++)
180 {
181 DMVector p;
182 if (!dmReadCoordinate(&line, &p.x, TRUE)) return FALSE;
183 if (!dmReadCoordinate(&line, &p.y, TRUE)) return FALSE;
184 if (!dmReadCoordinate(&line, &p.z, FALSE)) return FALSE;
185 if (dmAdd3DLineSpriteModelVertex(model, &p, &indices[vertex]) != DMERR_OK)
186 goto error;
187 line = dmSkipWhitespace(line, FALSE);
188 }
189
190 if (sscanf(line, "%d", &type) != 1)
191 {
192 dmError("No line type @ '%s'\n", line);
193 goto error;
194 }
195
196 for (vertex = 1; vertex <= nvertices; vertex++)
197 {
198 DM3DLine line;
199 line.v1 = indices[vertex - 1];
200 line.v2 = indices[vertex];
201 line.type = type;
202 if (dmAdd3DLineSpriteModelLine(model, &line, NULL) != DMERR_OK)
203 goto error;
204 }
205
206 return TRUE;
207 error:
208 dmFree(indices);
209 return FALSE;
210 }
211
212 static BOOL dmReadSprite(char *line, DM3DLineSpriteModel *model)
213 {
214 DMVector pt;
215 DM3DSprite spr;
216
217 line++;
218 if (!dmReadCoordinate(&line, &pt.x, TRUE)) return FALSE;
219 if (!dmReadCoordinate(&line, &pt.y, TRUE)) return FALSE;
220 if (!dmReadCoordinate(&line, &pt.z, FALSE)) return FALSE;
221 line = dmSkipWhitespace(line, FALSE);
222 if (*line != 'B')
223 {
224 dmError("No bitmap definition found for sprite.\n");
225 return FALSE;
226 }
227
228 spr.bitmap = atoi(line + 1);
229
230 if (dmAdd3DLineSpriteModelVertex(model, &pt, &spr.v) != DMERR_OK)
231 return FALSE;
232
233 if (dmAdd3DLineSpriteModelSprite(model, &spr, NULL) != DMERR_OK)
234 return FALSE;
235
236 return TRUE;
237 }
238
239 static BOOL dmReadBitmap(char *line, DM3DLineSpriteModel *model)
240 {
241 DM3DBitmap bmp, *rbmp;
242 int index;
243
244 strncpy(bmp.name, line + 1, sizeof(bmp.name));
245 bmp.img = NULL;
246
247 if (dmAdd3DLineSpriteModelBitmap(model, &bmp, &index) != DMERR_OK)
248 return FALSE;
249
250 rbmp = &(model->bitmaps[index]);
251 if (rbmp->img == NULL)
252 {
253 DMResource *res = dmf_create_stdio(rbmp->name, "rb");
254 if (res == NULL)
255 {
256 dmError("Could not open resource file '%s'.\n", rbmp->name);
257 return FALSE;
258 }
259 rbmp->img = dmLoadImage(res);
260 dmf_close(res);
261 if (rbmp->img == NULL)
262 {
263 dmError("Could not load image file '%s'.\n", rbmp->name);
264 return FALSE;
265 }
266 }
267 fprintf(stderr, "loaded '%s': %d: %p\n", rbmp->name, index, rbmp->img);
268 return TRUE;
269 }
270
271
272 int dmRead3DLineSpriteModel(DMResource *f, DM3DLineSpriteModel *model)
273 {
274 char line[512];
275
276 memset(model, 0, sizeof(*model));
277
278 while (dmfgets(line, sizeof(line), f) != NULL)
279 {
280 char *start = dmSkipWhitespace(line, FALSE);
281 switch (*start)
282 {
283 case 0:
284 case '#':
285 break;
286
287 case 'B':
288 if (!dmReadBitmap(start, model))
289 return DMERR_INVALID_DATA;
290 break;
291
292 case 'L':
293 if (!dmReadLineSegments(start, model))
294 return DMERR_INVALID_DATA;
295 break;
296
297 case 'S':
298 if (!dmReadSprite(start, model))
299 return DMERR_INVALID_DATA;
300 break;
301
302 default:
303 break;
304 }
305 }
306
307 return DMERR_OK;
308 }