Mercurial > hg > dmlib
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 } |