comparison Renderer/test_render/task/CreateSpan.cpp @ 283:55ea4465b1a2

fix test_render
author e065746@localhost.localdomain
date Fri, 05 Jun 2009 16:49:12 +0900
parents
children
comparison
equal deleted inserted replaced
282:ef061be0baff 283:55ea4465b1a2
1 #include "CreateSpan.h"
2 #include "viewer_types.h"
3
4 static const int SPAN_PACK_LOAD = 5;
5 static const int SPAN_PACK_STORE = 6;
6 static const int POLYGON_PACK_LOAD = 7;
7 static const int TILE_ALLOCATE = 8;
8 static const int TILE_LOAD = 9;
9 static const int TILE_STORE = 10;
10
11 static SpanPackPtr spack = NULL;
12 static SpanPackPtr send_spack = NULL;
13 static int prev_index = 0;
14
15 SchedDefineTask(CreateSpan);
16
17 static float
18 calc(float f1, float f2,int i, float base)
19 {
20 float ans;
21 ans = f1/f2*i + base;
22 return ans;
23 }
24
25
26 /**
27 * TrianglePack から、vMin, vMid, vMax を求める
28 *
29 * @param [triPack] TrianglePack
30 * @param [vMin] [vMid] [vMax]
31 */
32 static void
33 make_vertex(TrianglePack *triPack,
34 VertexPackPtr *vMin, VertexPackPtr *vMid, VertexPackPtr *vMax)
35 {
36 if (triPack->ver1.y <= triPack->ver2.y) {
37 if (triPack->ver2.y <= triPack->ver3.y) {
38 *vMin = &triPack->ver1;
39 *vMid = &triPack->ver2;
40 *vMax = &triPack->ver3;
41 } else if (triPack->ver3.y <= triPack->ver1.y) {
42 *vMin = &triPack->ver3;
43 *vMid = &triPack->ver1;
44 *vMax = &triPack->ver2;
45 } else {
46 *vMin = &triPack->ver1;
47 *vMid = &triPack->ver3;
48 *vMax = &triPack->ver2;
49 }
50 } else {
51 if (triPack->ver1.y <= triPack->ver3.y) {
52 *vMin = &triPack->ver2;
53 *vMid = &triPack->ver1;
54 *vMax = &triPack->ver3;
55 } else if (triPack->ver3.y <= triPack->ver2.y) {
56 *vMin = &triPack->ver3;
57 *vMid = &triPack->ver2;
58 *vMax = &triPack->ver1;
59 } else {
60 *vMin = &triPack->ver2;
61 *vMid = &triPack->ver3;
62 *vMax = &triPack->ver1;
63 }
64 }
65 }
66
67 static void
68 make_vMid10(VertexPack *v, VertexPack *vMin,
69 VertexPack *vMid, VertexPack *vMax)
70 {
71 //int d, d1;
72 float d;
73 int d1;
74
75 d = vMax->y - vMin->y;
76 d1 = (int)(vMid->y - vMin->y);
77
78 v->tex_x = calc(vMax->tex_x - vMin->tex_x, d, d1, vMin->tex_x);
79 v->tex_y = calc(vMax->tex_y - vMin->tex_y, d, d1, vMin->tex_y);
80 v->x = calc(vMax->x - vMin->x, d, d1, vMin->x);
81 v->y = vMid->y;
82 v->z = calc(vMax->z - vMin->z, d, d1, vMin->z);
83 }
84
85 /**
86 * 与えられた scale から、実際に使うテクスチャの Tapestry を選択する
87 *
88 * テクスチャは、オリジナルのサイズから、可能なかぎり 1/2 で縮小していき、
89 * 下の図の様に連続した領域に入れられる
90 *
91 * Tapestry (1)
92 * +---+---+---+---+
93 * | 0 | 1 | 2 | 3 |
94 * +---+---+---+---+
95 * | 4 | 5 | 6 | 7 | (2)
96 * +---+---+---+---+ +---+---+
97 * | 8 | 9 | 10| 11| | 16| 17| (3)
98 * +---+---+---+---+ +---+---+ +---+
99 * | 12| 13| 14| 15| | 18| 19| | 20|
100 * +---+---+---+---+ +---+---+ +---|
101 *
102 * (1) (2) (3)
103 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
104 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | * | * | 14| 15| 16| 17| 18| 19| 20|
105 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
106 *
107 * scale の値から、各 Tapestry の先頭アドレスを返す
108 *
109 * @param[in] tw Width of texture
110 * @param[in] th Height of texture
111 * @param[in] scale テクスチャの縮小率 (= 2^n)
112 * @param[in] addr_top テクスチャの先頭アドレス (上の図での (1)
113 * @return scale に対応する Tapestry のアドレス (上の図での (1) or (2) or(3)
114 */
115 static uint32*
116 getTapestry(int tw, int th, int scale, uint32 *addr_top)
117 {
118 int index = 0;
119
120 for (int s = 1; s < scale; s <<= 1) {
121 index += tw*th;
122 tw >>= 1; /* tw /= 2 */
123 th >>= 1;
124 }
125
126 return addr_top + index;
127 }
128
129
130 /**
131 * span の width,height と texture の width,height を比べて
132 * span を描画する際に使う texture の比率を求める
133 *
134 * @param[in] width Width of span
135 * @param[in] height Height of span
136 * @param[in] tex_width Width of 1/1 texture that span use
137 * @param[in] tex_height Height of 1/1 texture that span use
138 * @param[in] scale_max この Span で使う texture の最大縮小率
139 * 計算結果が scale_max 以上になるのを防ぐ
140 * @return 描画に使う texture の比率
141 * width と height は 1/scale の画像を使う
142 *
143 */
144 static int
145 getScale(int width, int height, int tex_width, int tex_height, int scale_max)
146 {
147 int base, tex_base;
148 int scale = 1;
149
150 /**
151 * width と height で、長い方を基準に、
152 * texture の scale を決める
153 */
154 if (width > height) {
155 base = width;
156 tex_base = tex_width;
157 } else {
158 base = height;
159 tex_base = tex_height;
160 }
161
162 if (tex_base > base) {
163 int t_scale = tex_base/base;
164 while (t_scale >>= 1) {
165 scale <<= 1;
166 }
167 }
168
169 return (scale > scale_max) ? scale_max : scale;
170 //return scale_max;
171 }
172
173 /**
174 * x軸に水平な辺を持つ三角形ポリゴンから、
175 * Span を抜き出す
176 *
177 * @param[in] spackList triangle から生成された span を格納する List
178 * @param[in] charge_y_top 担当する y の範囲開始地点
179 * @param[in] charge_y_end 担当する y の範囲終了地点
180 * @param[in] tex_addr triangle が参照するテクスチャの先頭アドレス
181 * @param[in] tex_width テクスチャの width
182 * @param[in] tex_height テクスチャの height
183 * @param[in] tex_scale_max テクスチャの最大縮小率 (2^n)
184 * @param[in] vMin triangle の座標
185 * @param[in] vMid triangle の座標。triangle を二つに分けて出来た新しい座標
186 * @param[in] vMid10 triangle の座標
187 * @param[in] length_y 分割する前の Triangle の y の長さ
188 * @param[in] tex_y_len 分割する前の Triangle に貼られている Texture の
189 * 長さの割合 (0 ... 1)
190 */
191 void
192 CreateSpan::half_triangle(SpanPackPtr *spackList,
193 int charge_y_top, int charge_y_end,
194 TriangleTexInfoPtr tex_info,
195 VertexPack *vMin,VertexPack *vMid,VertexPack *vMid10,
196 int length_y, float tex_y_len)
197 {
198 float tmp_z,tmp_tex1, tmp_tex2 ,tmp_tey1,tmp_tey2;
199 float tmp_xpos,tmp_end,tmp_zpos;
200 float start_z, end_z;
201 float start_tex_x, end_tex_x, start_tex_y, end_tex_y;
202 int x, y, length;
203
204 #if 1
205 // これじゃないと
206 // テクスチャの貼りに微妙に隙間が。謎だ
207 int start_y = (int)vMid->y;
208 int end_y = (int)vMin->y;
209 #else
210 float start_y = vMid->y;
211 float end_y = vMin->y;
212 #endif
213 float div_y = start_y - end_y;
214 int k = 0;
215 int l = 1;
216
217 SpanPackPtr tmp_spack;
218
219 /**
220 * 三角形ポリゴンをx軸に水平に二つに分けようとして
221 * ある一辺がすでに水平だった場合、つまり
222 *
223 * |\
224 * | \
225 * | \
226 * -----
227 *
228 *
229 * 上のようなポリゴンだった場合は、本来なら上の部分の三角形にだけ
230 * half_triangle の処理をするべきだが、現在の処理だと
231 * この half_triangle に「上の部分の三角形」と、
232 * 「『下の部分の三角形と判断してしまった』直線」が来てしまう。
233 * 直線の部分が来ると、calc() で 0 除算とかで、値不定で暴走するので
234 * 現在はこれで代用。
235 * half_triangle 呼ぶ前にこれを判断できれば良いかもしれない。
236 * てかこんなんでいいのかよ。。。
237 */
238 #if 1
239 if ((int)div_y == 0) {
240 return;
241 }
242 #else
243 if (vMid10->x == vMin->x && vMid10->y == vMin->y) {
244 return;
245 }
246 #endif
247
248 if (div_y < 0) {
249 div_y = -div_y;
250 k = 1;
251 l = -1;
252 }
253
254 for (int i = k; i < (int)div_y+1; i++) {
255 y = (int)vMin->y + i*l;
256 #if 1
257
258 /**
259 * 担当 y 範囲内
260 */
261 if (charge_y_top <= y && y <= charge_y_end) {
262 // 1..8 を index0, 9..16 を index1 にするために y を -1
263 int index = (y-1) / split_screen_h;
264
265 /**
266 * 違う SpanPack を扱う場合、
267 * 現在の SpanPack をメインメモリに送り、
268 * 新しい SpanPack を取ってくる
269 */
270 if (index != prev_index) {
271 tmp_spack = spack;
272 spack = send_spack;
273 send_spack = tmp_spack;
274
275 smanager->dma_wait(SPAN_PACK_STORE);
276 smanager->dma_store(send_spack, (uint32)spackList[prev_index],
277 sizeof(SpanPack), SPAN_PACK_STORE);
278
279 smanager->dma_load(spack, (uint32)spackList[index],
280 sizeof(SpanPack), SPAN_PACK_LOAD);
281 prev_index = index;
282 smanager->dma_wait(SPAN_PACK_LOAD);
283 }
284
285 /**
286 * 書き込む SpanPack が満杯だったら
287 * メインメモリで allocate した領域 (next) を持ってきて
288 * 現在の spack->next につなぎ、next を次の spack とする。
289 */
290 if (spack->info.size >= MAX_SIZE_SPAN) {
291 SpanPackPtr next;
292
293 smanager->mainMem_alloc(0, sizeof(SpanPack));
294 smanager->mainMem_wait();
295 next = (SpanPackPtr)smanager->mainMem_get(0);
296
297 spack->next = next;
298
299 tmp_spack = spack;
300 spack = send_spack;
301 send_spack = tmp_spack;
302
303 smanager->dma_wait(SPAN_PACK_STORE);
304 smanager->dma_store(send_spack, (uint32)spackList[index],
305 sizeof(SpanPack), SPAN_PACK_STORE);
306
307 spackList[index] = next;
308
309 smanager->dma_load(spack, (uint32)spackList[index],
310 sizeof(SpanPack), SPAN_PACK_LOAD);
311 smanager->dma_wait(SPAN_PACK_LOAD);
312 spack->init((index+1)*split_screen_h);
313 }
314 } else {
315 /**
316 * 担当範囲外だったら無視
317 */
318 continue;
319 }
320
321 tmp_xpos = calc(vMid10->x - vMin->x ,div_y, i, vMin->x);
322 tmp_end = calc(vMid->x - vMin->x ,div_y, i, vMin->x);
323 tmp_z = calc(vMid10->z - vMin->z ,div_y, i, vMin->z);
324 tmp_zpos = calc(vMid->z - vMin->z ,div_y, i, vMin->z);
325
326 length = (tmp_xpos > tmp_end)
327 ? (int)tmp_xpos - (int)tmp_end : (int)tmp_end - (int)tmp_xpos;
328 if (length == 0) {
329 continue;
330 }
331
332 tmp_tex1 =((i/(div_y)) * vMid10->tex_x) +
333 ( ((div_y - i)/(div_y)) * vMin->tex_x);
334 tmp_tex2 =( (i/(div_y)) * vMid->tex_x) +
335 ( ((div_y - i)/(div_y)) * vMin->tex_x);
336
337 tmp_tey1 =( (i/(div_y)) * vMid10->tex_y) +
338 ( ((div_y - i)/(div_y)) * vMin->tex_y);
339 tmp_tey2 =( (i/(div_y)) * vMid->tex_y) +
340 ( ((div_y - i)/(div_y)) * vMin->tex_y);
341
342 if (tmp_xpos > tmp_end) {
343 x = (int)tmp_end;
344 length = (int)(tmp_xpos)-(int)(tmp_end)+1;
345 start_z = tmp_zpos;
346 end_z = tmp_z;
347 start_tex_x = tmp_tex2;
348 end_tex_x = tmp_tex1;
349 start_tex_y = tmp_tey2;
350 end_tex_y = tmp_tey1;
351 } else {
352 x = (int)tmp_xpos;
353 length = (int)(tmp_end)-(int)(tmp_xpos)+1;
354 start_z = tmp_z;
355 end_z = tmp_zpos;
356 start_tex_x = tmp_tex1;
357 end_tex_x = tmp_tex2;
358 start_tex_y = tmp_tey1;
359 end_tex_y = tmp_tey2;
360 }
361
362 smanager->dma_wait(SPAN_PACK_LOAD);
363
364 Span *span = &spack->span[spack->info.size++];
365
366 span->x = x;
367 span->y = y;
368 span->length_x = length;
369 span->start_z = start_z;
370 span->end_z = end_z;
371 span->tex_x1 = start_tex_x;
372 span->tex_x2 = end_tex_x;
373 span->tex_y1 = start_tex_y;
374 span->tex_y2 = end_tex_y;
375
376
377 float tex_x_len = span->tex_x2 - span->tex_x1;
378
379 /**
380 * tex_x_len, tex_y_len を掛ける理由は
381 * Changelog の 2008-12-16 を参照
382 */
383 int scale = getScale(span->length_x, length_y,
384 (int)(span->tex_width*tex_x_len),
385 (int)(span->tex_height*tex_y_len),
386 tex_info->scale_max);
387 //scale = tex_info->scale_max;
388
389 uint32 *tapestry = getTapestry(tex_info->width,
390 tex_info->height, scale,
391 tex_info->addr);
392 span->tex_addr = tapestry;
393 span->tex_width = tex_info->width/scale;
394 span->tex_height = tex_info->height/scale;
395 }
396 #else
397
398 /**
399 * ここに SIMD 化した記述をしようとして断念
400 */
401
402 #endif
403
404 }
405
406
407 int
408 CreateSpan::run(void *rbuf, void *wbuf)
409 {
410 PolygonPack *pp = (PolygonPack*)smanager->get_input(0);
411 PolygonPack *next_pp =
412 (PolygonPack*)smanager->allocate(sizeof(PolygonPack));
413 PolygonPack *free_pp = next_pp;
414 PolygonPack *tmp_pp;
415
416 TrianglePackPtr triPack;
417 VertexPackPtr vMin, vMid, vMax;
418 VertexPackPtr vMid10
419 = (VertexPackPtr)smanager->allocate(sizeof(VertexPack));
420
421 SpanPackPtr *spackList = (SpanPackPtr*)smanager->get_input(1);
422 spack = (SpanPackPtr)smanager->get_input(2);
423 send_spack = (SpanPackPtr)smanager->allocate(sizeof(SpanPack));
424 prev_index = get_param(0);
425
426 // spack と send_spack は swap しながら DMA を繰り返すので
427 // 自分で allocate した send_spack を覚えてないといけない
428 SpanPackPtr free_spack = send_spack;
429
430 int charge_y_top = get_param(1);
431 int charge_y_end = get_param(2);
432
433 do {
434 if (pp->next != NULL) {
435 smanager->dma_load(next_pp, (uint32)pp->next,
436 sizeof(PolygonPack), POLYGON_PACK_LOAD);
437 } else {
438 next_pp = NULL;
439 }
440
441 for (int i = 0; i < pp->info.size; i++) {
442 triPack = &pp->tri[i];
443
444 TriangleTexInfoPtr tri_tex_info = &triPack->tex_info;
445
446 make_vertex(triPack, &vMin, &vMid, &vMax);
447 make_vMid10(vMid10, vMin, vMid, vMax);
448
449 /**
450 * ポリゴンを、x軸に水平に分割して二つの三角形を作り、
451 * それぞれから Span を求める
452 *
453 * vMax
454 * |\
455 * | \
456 * | \
457 * | \
458 * vMid10 ------ vMid
459 * | /
460 * | /
461 * | /
462 * |/
463 * vMin
464 *
465 * (vMax, vMid, vMin) という triangle を
466 * (vMax, vMid, vMid10) (vMin, vMid, vMid10) という
467 * 二つの Triangle に分けている
468 */
469 half_triangle(spackList, charge_y_top, charge_y_end,
470 tri_tex_info, vMin, vMid, vMid10,
471 (int)(vMax->y - vMin->y), vMax->tex_y - vMin->tex_y);
472 half_triangle(spackList, charge_y_top, charge_y_end,
473 tri_tex_info, vMax, vMid, vMid10,
474 (int)(vMax->y - vMin->y), vMax->tex_y - vMin->tex_y);
475 }
476
477 smanager->dma_wait(POLYGON_PACK_LOAD);
478
479 tmp_pp = pp;
480 pp = next_pp;
481 next_pp = tmp_pp;
482 } while (pp);
483
484 smanager->dma_wait(SPAN_PACK_STORE);
485 smanager->dma_store(spack, (uint32)spackList[prev_index],
486 sizeof(SpanPack), SPAN_PACK_STORE);
487 smanager->dma_wait(SPAN_PACK_STORE);
488
489 free(free_pp);
490 free(free_spack);
491 free(vMid10);
492
493 return 0;
494 }