THREED.H
[目次 | 型・クラス・構造体 | マクロ]
1|/***********************************************************************
2|* 1. <<< 浮動小数版・三次元グラフィック関連 [ThreeD] >>>
3|************************************************************************/
4|
5|#ifndef __THREED_H
6|#define __THREED_H
7|
8|/*----------------------------------------------------------------------
9|[Module Property]
10|name = ThreeD
11|title = 三次元グラフィック
12|category = グラフィック
13|src = threed.c
14|depend = Types
15|priority =
16|accord =
17|----------------------------------------------------------------------*/
18|
19|#ifndef USES_PRIORITY_HEADER
20|/*[START_OF_PRIORITY_HEADER]*/
21|
22|#define USES_THREED
23|
24|#ifndef THREED_TYPEDEF
25|#define THREED_TYPEDEF
26|typedef struct _ThreeD_XYZ ThreeD_XYZ;
27|typedef struct _ThreeD_XYZ2 ThreeD_XYZ2;
28|typedef struct _ThreeD_Dir ThreeD_Dir;
29|typedef struct _ThreeD_Vect ThreeD_Vect;
30|typedef struct _ThreeD_ViewL ThreeD_ViewL;
31|typedef struct _ThreeD_Line ThreeD_Line;
32|typedef struct _ThreeD_Surf ThreeD_Surf;
33|typedef struct _ThreeD_Poly ThreeD_Poly;
34|typedef struct _ThreeD_ShPoly ThreeD_ShPoly;
35|typedef struct _ThreeD_PolyS ThreeD_PolyS;
36|typedef struct _ThreeD_TwoD ThreeD_TwoD;
37|#endif
38|
39|/*[END_OF_PRIORITY_HEADER]*/
40|#endif /* USES_PRIORITY_HEADER */
41|
42|
43|
44|
45|
46|
47|/*-------------------------------------------------------------------*/
48|/* 2. <<< Interface Area ------------------------------------------ >>> */
49|/*-------------------------------------------------------------------*/
50|
51|
52|
53|/***********************************************************************
54|* 3. <<< [ThreeD_XYZ] 三次元の座標値(double型) >>>
55|*【補足】
56|*・この座標は、右手系デカルト座標で、Z 方向は、X から Y に回した右ネジ
57|* 方向です。
58|*
59|************************************************************************/
60|struct _ThreeD_XYZ {
61| double x,y,z;
62|};
63|void ThreeD_XYZ_init( ThreeD_XYZ*, double x, double y, double z );
64|void ThreeD_XYZ_get2D( ThreeD_XYZ*, ThreeD_ViewL* view, ThreeD_XYZ* out );
65|void ThreeD_XYZ_get3D( ThreeD_XYZ*, ThreeD_ViewL* view, ThreeD_XYZ* out );
66|void ThreeD_XYZ_move( ThreeD_XYZ*, ThreeD_XYZ* vect, ThreeD_Dir* dir,
67| ThreeD_XYZ* out );
68|void ThreeD_XYZ_rot( ThreeD_XYZ*, ThreeD_Dir* dir, ThreeD_XYZ* out );
69|void ThreeD_XYZ_rotR( ThreeD_XYZ*, ThreeD_Dir* dir, ThreeD_XYZ* out );
70|void ThreeD_XYZ_rotDir( ThreeD_XYZ* in, ThreeD_XYZ* axis_xyz,
71| ThreeD_Dir* axis_dir, ThreeD_XYZ* out );
72|double ThreeD_XYZ_getDistance( ThreeD_XYZ* a, ThreeD_XYZ* b );
73|void ThreeD_XYZ_getZCross( ThreeD_XYZ* p1, ThreeD_XYZ* p2,
74| double z, ThreeD_XYZ* p );
75|double ThreeD_XYZ_getSurfDistanceL( ThreeD_XYZ* p, ThreeD_Surf* surf,
76| ThreeD_Line* line );
77|#ifdef USES_TWOD
78|bool ThreeD_XYZ_isInPoly( ThreeD_XYZ* p, ThreeD_Poly* poly,
79| TwoD_XY* poly2_xy, size_t poly2_xy_sizeof );
80|#endif
81|#ifndef ERRORS_CUT_DEBUG_TOOL
82| void ThreeD_XYZ_print( ThreeD_XYZ*, const char* title );
83|#endif
84|
85|
86|
87|
88|/***********************************************************************
89|* 4. <<< [ThreeD_XYZ2] 三次元の座標値(float型) >>>
90|*【補足】
91|*・この座標は、右手系デカルト座標で、Z 方向は、X から Y に回した右ネジ
92|* 方向です。
93|*
94|************************************************************************/
95|struct _ThreeD_XYZ2 {
96| float x,y,z;
97|};
98|
99|float ThreeD_XYZ2_getDistance( ThreeD_XYZ2* a, ThreeD_XYZ2* b );
100|#ifndef ERRORS_CUT_DEBUG_TOOL
101| void ThreeD_XYZ2_print( ThreeD_XYZ2*, const char* title );
102|#endif
103|
104|
105|
106|/***********************************************************************
107|* 5. <<< [ThreeD_Dir] 三次元の方向, 角度 >>>
108|*【役割】
109|*・右手系デカルト座標の X 軸正方向を基準として、経度θ(X軸正方向→Y軸正方向
110|* の角度)と緯度φ(XY平面→Z軸正方向の角度)で方向を指定します。
111|*・また、その方向を軸として、反時計周りにひねりの角度を指定します。
112|* ただし、Z軸正の向きが上向きになる角度を0度とします。
113|*・三次元ワールド座標も二次元ワールド座標も右手系デカルト座標です。
114|*
115|************************************************************************/
116|struct _ThreeD_Dir { /* 角度の単位はラジアン、正方向は時計周りと反対です */
117| double th; /*θ=ワールド座標の経度(x→y) */
118| double fy; /*φ=ワールド座標の緯度(xy→z) */
119| double af; /*α=スクリーン座標の Z軸回転角度 */
120|
121| /*** キャッシュ的変数 ***/
122| double sin_th, cos_th; /* 角度 θ(x→y) の三角関数 */
123| double sin_fy, cos_fy; /* 角度 φ(xy→z) の三角関数 */
124| double sin_af, cos_af; /* 角度 α(視点軸反時計周り) の三角関数 */
125|};
126|
127|void ThreeD_Dir_initDef( ThreeD_Dir* );
128|void ThreeD_Dir_init( ThreeD_Dir*, double th, double fy, double af );
129|void ThreeD_Dir_init2( ThreeD_Dir*, double dx, double dy,
130| double dz, double af );
131|#ifndef ERRORS_CUT_DEBUG_TOOL
132| void ThreeD_Dir_print( ThreeD_Dir*, const char* title );
133|#endif
134|
135|
136|
137|/*************************************************************************
138|* 6. <<< [ThreeD_Vect] 三次元ベクトル >>>
139|**************************************************************************/
140|struct _ThreeD_Vect {
141| double x, y, z;
142|};
143|
144|void ThreeD_Vect_init( ThreeD_Vect*, double x, double y, double z );
145|void ThreeD_Vect_initBy2XYZ( ThreeD_Vect*, ThreeD_XYZ* p, ThreeD_XYZ* p0 );
146|void ThreeD_Vect_initBy2XYZ2( ThreeD_Vect*, ThreeD_XYZ2* p, ThreeD_XYZ2* p0 );
147|void ThreeD_Vect_initNor( ThreeD_Vect*, ThreeD_XYZ p[] );
148|void ThreeD_Vect_initNor2( ThreeD_Vect*, ThreeD_XYZ2 p[] );
149|void ThreeD_Vect_chgToUnit( ThreeD_Vect* );
150|double ThreeD_Vect_getLen( ThreeD_Vect* );
151|double ThreeD_Vect_getDirLen( ThreeD_Vect*, ThreeD_Vect* dir );
152|void ThreeD_Vect_getDirVect( ThreeD_Vect* in, ThreeD_Vect* dir,
153| ThreeD_Vect* out );
154|double ThreeD_Vect_getInnerProd( ThreeD_Vect*, ThreeD_Vect* );
155|double ThreeD_Vect_getCos( ThreeD_Vect*, ThreeD_Vect* );
156|#ifndef ERRORS_CUT_DEBUG_TOOL
157| void ThreeD_Vect_print( ThreeD_Vect*, const char* title );
158|#endif
159|
160|
161|
162|/***********************************************************************
163|* 7. <<< [ThreeD_ViewL] 視線, 視点 ★>>>
164|*【補足】
165|*
166|*
167|*
168|*
169|* 8. <<< [三次元ワールド座標,二次元ワールド座標] >>>
170|*・本モジュールでは、一般的な三次元のワールド座標を
171|* 『三次元ワールド座標』と呼んでいます。三次元座標変換により得られる
172|* スクリーンの中央を0とした座標を『二次元ワールド座標と』呼んでいます。
173|*・(参考)二次元ワールド座標へ変換する - ThreeD_XYZ_get2D 関数
174|************************************************************************/
175|struct _ThreeD_ViewL {
176| ThreeD_XYZ p; /* 視点の位置(仮想視点、ワールド座標)*/
177| ThreeD_Dir dir; /* 視線の方向 */
178| double diffV; /* 仮想視点から投影面までの距離 */
179| double diffC; /* 投影面から前面クリッピング領域までの距離 */
180| double diffU; /* ユーザ視点から投影面までの距離 */
181|};
182|
183|void ThreeD_ViewL_initDef( ThreeD_ViewL* );
184|void ThreeD_ViewL_init( ThreeD_ViewL*,
185| double x, double y, double z,
186| double th, double fy, double af,
187| double diffV, double diffC, double diffU );
188|void ThreeD_ViewL_setXYZ( ThreeD_ViewL*, double x, double y, double z );
189|void ThreeD_ViewL_setDir( ThreeD_ViewL*, double th, double fy, double af );
190|void ThreeD_ViewL_setDirAndMove( ThreeD_ViewL* this,
191| double th, double fy, double af,
192| double tx, double ty, double tz );
193|void ThreeD_ViewL_setTarget( ThreeD_ViewL*, double x, double y,
194| double z, double af );
195|
196|void ThreeD_ViewL_getUserViewP( ThreeD_ViewL*, ThreeD_XYZ* userViewP );
197|void ThreeD_ViewL_move( ThreeD_ViewL*,
198| double dx, double dy, double dz );
199|void ThreeD_ViewL_rot( ThreeD_ViewL*,
200| double d_th, double d_fy, double d_af );
201|
202|#ifndef ERRORS_CUT_DEBUG_TOOL
203| void ThreeD_ViewL_print( ThreeD_ViewL*, const char* title );
204|#endif
205|
206|
207|/*************************************************************************
208|* 9. <<< [ThreeD_Line] 直線 >>>
209|*【補足】
210|*・三次元空間における直線の方程式は、次の通りです。
211|*
212|* ただし、x,y,z は変数、x1,y1,z1 は直線上のある1点の座標、
213|* l,m,n は、方向余弦(単位ベクトルの x,y,z 成分)です。
214|**************************************************************************/
215|struct _ThreeD_Line {
216| ThreeD_XYZ p1; /* 直線上のある1点の座標 */
217| double xcos, ycos, zcos; /* 方向余弦(単位ベクトルの x,y,z 成分)*/
218|};
219|
220|void ThreeD_Line_init( ThreeD_Line*, ThreeD_XYZ* p1, ThreeD_XYZ* p2 );
221|
222|
223|
224|/*************************************************************************
225|* 10. <<< [ThreeD_Surf] 平面 >>>
226|*【役割】
227|*・三次元における、面積が無限大の平面です。
228|*・係数 a,b,c は、法線ベクトルの成分に対応しています。
229|**************************************************************************/
230|struct _ThreeD_Surf {
231| double a,b,c,d; /* 平面の方程式 ax+by+cz+d=0 */
232|};
233|
234|void ThreeD_Surf_initByP3( ThreeD_Surf*, ThreeD_XYZ p[] );
235|void ThreeD_Surf_initByP3_2( ThreeD_Surf*, ThreeD_XYZ2 p[] );
236|void ThreeD_Surf_initByP3_3( ThreeD_Surf*,
237| double p1x, double p1y, double p1z,
238| double p2x, double p2y, double p2z,
239| double p3x, double p3y, double p3z );
240|double ThreeD_Surf_getZ( ThreeD_Surf*, double x, double y );
241|void ThreeD_Surf_getLineCross( ThreeD_Surf*, ThreeD_Line* line,
242| ThreeD_XYZ* out );
243|int ThreeD_Surf_cmpFront( ThreeD_Surf*, ThreeD_XYZ* viewP );
244|#ifndef ERRORS_CUT_DEBUG_TOOL
245| void ThreeD_Surf_print( ThreeD_Surf* );
246|#endif
247|
248|
249|
250|/*************************************************************************
251|* 11. <<< [ThreeD_Poly] ポリゴン >>>
252|*【役割】
253|*・三次元座標での多角形の平面を「ポリゴン」と呼ぶことにします。
254|*・頂点の数が4つ以上の場合、それらが同一平面上にある必要があります。
255|*・頂点の配列 p_array は、表側から見て反時計周りに並べます。
256|*・頂点は、すべて凸型である必要があります。
257|**************************************************************************/
258|struct _ThreeD_Poly {
259| ThreeD_XYZ* p_array; /* 頂点座標の配列の先頭アドレス */
260| int n; /* n 角形 */
261| ThreeD_Surf surf; /* 平面方程式 */
262| int color; /* 色 */
263|};
264|
265|void ThreeD_Poly_init( ThreeD_Poly*, ThreeD_XYZ* p_array, int n,
266| int color );
267|void ThreeD_Poly_initShadow( ThreeD_Poly*, ThreeD_Poly* shadowed,
268| ThreeD_Poly* shadowing, ThreeD_XYZ* light,
269| ThreeD_XYZ* xyzs, size_t xyzs_sizeof );
270|void ThreeD_Poly_getCenter( ThreeD_Poly*, ThreeD_XYZ* center );
271|int ThreeD_Poly_cmpFront( ThreeD_Poly*, ThreeD_XYZ* viewP );
272|
273|#ifdef USES_SCALE
274|#ifdef USES_TWOD
275|int ThreeD_Poly_getZVal( ThreeD_Poly*, int sx, int sy,
276| ThreeD_ViewL* view, Scale* scale );
277|#endif /* USES_TWOD */
278|#endif /* USES_SCALE */
279|
280|#ifdef USES_DRAW
281|#ifdef USES_SCALE
282|#ifdef USES_XORPAINT
283|void ThreeD_Poly_draw( ThreeD_Poly*, ThreeD_ViewL* view, Draw* draw,
284| Scale* scale, XorPaint* paint );
285|void ThreeD_Poly_draw2( ThreeD_Poly*, ThreeD_ViewL* view, Draw* draw,
286| Scale* scale, XorPaint* paint );
287|#endif /* USES_XORPAINT */
288|#endif /* USES_SCALE */
289|#endif /* USES_DRAW */
290|
291|
292|
293|/*************************************************************************
294|* 12. <<< [ThreeD_ShPoly] 影映りポリゴン >>>
295|*【役割】
296|*・影を映されることができるポリゴンです。つまり、影ポリゴンと関連付けさせ
297|* られます。
298|*・lightFlag については、ThreeD_ShPoly_shadowing 関数を参考。
299|**************************************************************************/
300|#define ThreeD_ShPoly_mSh 50 /* 1つの影映りポリゴンに映る影の最大数+1 */
301|
302|struct _ThreeD_ShPoly {
303| ThreeD_Poly poly; /* extend */ /* 影映りポリゴン */
304| ThreeD_Poly* shadow[ThreeD_ShPoly_mSh]; /* 影ポリゴン, NULL まで */
305| int lightFlag; /* 光のある方向 */
306|};
307|
308|/* 単体の処理 */
309|void ThreeD_ShPoly_init( ThreeD_ShPoly*, ThreeD_XYZ* p_array, int n,
310| int color );
311|#ifdef USES_ARRX
312|void ThreeD_ShPoly_shadowing( ThreeD_ShPoly*, ArrX* shPolys,
313| ThreeD_XYZ* light, ArrX_Buf* shadowBuf, ArrX_Buf* xyzBuf );
314|#ifdef USES_DRAW
315|#ifdef USES_SCALE
316|#ifdef USES_XORPAINT
317|#ifdef USES_MASK
318|void ThreeD_ShPoly_draw2( ThreeD_ShPoly*, ThreeD_ViewL* view, Draw* draw,
319| Scale* scale, XorPaint* paint );
320|#endif /* USES_MASK */
321|#endif /* USES_XORPAINT */
322|#endif /* USES_SCALE */
323|#endif /* USES_DRAW */
324|#endif /* USES_ARRX */
325|
326|/* 全部の処理 */
327|#ifdef USES_ARRX
328|void ThreeD_ShPoly_shadowingAll( ArrX* shPolys, ThreeD_XYZ* light );
329|#endif /* USES_ARRX */
330|
331|
332|
333|/*************************************************************************
334|* 13. <<< [ThreeD_PolyS] ソート用ポリゴン >>>
335|**************************************************************************/
336|struct _ThreeD_PolyS {
337| ThreeD_Poly* poly; /* ポリゴン */
338| double dist; /* 視点からの距離 */
339|};
340|#ifdef USES_ARRX
341|#ifdef USES_XORPAINT
342|void ThreeD_PolyS_draw( ArrX* polys, void** sortBuf, size_t sortBuf_sizeof,
343| ThreeD_ViewL* view, Draw* draw, Scale* scale, XorPaint* paint );
344|void ThreeD_PolyS_drawSh( ArrX* polys, void** sortBuf, size_t sortBuf_sizeof,
345| ThreeD_ViewL* view, Draw* draw, Scale* scale, XorPaint* paint );
346|#endif /* USES_XORPAINT */
347|#endif /* USES_ARRX */
348|
349|
350|
351|/*************************************************************************
352|* 14. <<< [ThreeD_TwoD] 三次元空間内の二次元座標 >>>
353|**************************************************************************/
354|struct _ThreeD_TwoD {
355| ThreeD_Vect x_coord; /* X 座標単位ベクトル */
356| ThreeD_Vect y_coord; /* Y 座標単位ベクトル */
357|};
358|void ThreeD_TwoD_initByP3( ThreeD_TwoD*, ThreeD_XYZ p[] );
359|void ThreeD_TwoD_initByPoly( ThreeD_TwoD*, ThreeD_Poly* );
360|#ifndef ERRORS_CUT_DEBUG_TOOL
361| void ThreeD_TwoD_print( ThreeD_TwoD* );
362|#endif
363|
364|
365|
366|/*-------------------------------------------------------------------*/
367|/* 15. <<< Mapping Area -------------------------------------------- >>> */
368|/*-------------------------------------------------------------------*/
369|
370|
371|
372|/*************************************************************************
373|* 16. <<< [ThreeD_Vect_init] 初期化する >>>
374|*【補足】
375|*・単位ベクトルを作成する場合、初期化した後に ThreeD_Vect_chgToUnit 関数を
376|* 呼び出します。
377|**************************************************************************/
378|#define ThreeD_Vect_init( this, xx, yy, zz ) \
379| ( (this)->x = (xx), (this)->y = (yy), (this)->z = (zz) )
380|
381|
382|
383|/*************************************************************************
384|* 17. <<< [ThreeD_Vect_initBy2XYZ] 2点から初期化する >>>
385|*【補足】
386|*・p0 から p へのベクトルを作成します。型は、ThreeD_XYZ です。
387|**************************************************************************/
388|#define ThreeD_Vect_initBy2XYZ( this, p, p0 ) \
389| ( (this)->x = (p)->x - (p0)->x, \
390| (this)->y = (p)->y - (p0)->y, \
391| (this)->z = (p)->z - (p0)->z )
392|
393|
394|
395|/*************************************************************************
396|* 18. <<< [ThreeD_Vect_initBy2XYZ2] 2点から初期化する >>>
397|*【補足】
398|*・ThreeD_Vect_initBy2XYZ との違いは、引数の型のみです。
399|*・型は、ThreeD_XYZ2 です。
400|**************************************************************************/
401|#define ThreeD_Vect_initBy2XYZ2 ThreeD_Vect_initBy2XYZ
402|
403|
404|
405|/*************************************************************************
406|* 19. <<< [ThreeD_Vect_initBy2XYZ3] 2点から初期化する >>>
407|*【補足】
408|*・ThreeD_Vect_initBy2XYZ との違いは、引数の型のみです。
409|*・型は、ThreeD2_XYZ です。
410|**************************************************************************/
411|#define ThreeD_Vect_initBy2XYZ3( this, p, p0 ) \
412| ( (this)->x = (double)((p)->x - (p0)->x), \
413| (this)->y = (double)((p)->y - (p0)->y), \
414| (this)->z = (double)((p)->z - (p0)->z) )
415|
416|
417|
418|/*************************************************************************
419|* 20. <<< [ThreeD_Vect_initNor] 平面の法線ベクトルとして初期化する >>>
420|*【引数】
421|* ・ThreeD_XYZ p[3]; 平面を含む3点
422|*【補足】
423|*・3点の順番は、その3点からできる三角形を表から見て左回りに指定します。
424|*・3点は1つの直線上に並ばないようにしてください。
425|*・nor = normal = 法線
426|*・void ThreeD_Vect_initNor( ThreeD_Vect* this, ThreeD_XYZ p[] );
427|**************************************************************************/
428|#define ThreeD_Vect_initNor( this, p ) \
429| { \
430| ThreeD_Surf surf; \
431| ThreeD_Surf_initByP3( &surf, p ); \
432| ThreeD_Vect_init( this, surf.a, surf.b, surf.c ); \
433| }
434|
435|
436|
437|/*************************************************************************
438|* 21. <<< [ThreeD_Vect_initNor2] 平面の法線ベクトルとして初期化する >>>
439|*【引数】
440|* ・ThreeD_XYZ2 p[3]; 平面を含む3点
441|*【補足】
442|*・ThreeD_Vect_initNor との違いは、引数の型のみです。
443|**************************************************************************/
444|#define ThreeD_Vect_initNor2( this, p ) \
445| { \
446| ThreeD_Surf surf; \
447| ThreeD_Surf_initByP3_2( &surf, p ); \
448| ThreeD_Vect_init( this, surf.a, surf.b, surf.c ); \
449| }
450|
451|
452|
453|/*************************************************************************
454|* 22. <<< [ThreeD_Vect_getInnerProd] ベクトルの内積(A・B)>>>
455|*【補足】
456|*・ベクトルの内積は、次の性質があります。
457|* ・2つのベクトルの方向が一致しているか、90°以上反対方向か判定できます。
458|* ・単位ベクトルとない積を取ることで、方向成分(長さ)を取り出せます。
459|* そのベクトルは、ThreeD_Vect_getDirVect 関数で取得できます。
460|* その長さは、ThreeD_Vect_getDirLen 関数で取得できます。
461|*・内積を英語で言うと inner product です。
462|**************************************************************************/
463|#define ThreeD_Vect_getInnerProd( a, b ) \
464| ( (a)->x * (b)->x + (a)->y * (b)->y + (a)->z * (b)->z )
465|
466|
467|
468|/*************************************************************************
469|* 23. <<< [ThreeD_Vect_getDirLen] ベクトルの方向成分の長さを取得する >>>
470|*【補足】
471|*・dir には、単位ベクトルを指定してください。
472|*・_CHECKER マクロが定義されていると、関数になります
473|**************************************************************************/
474|#ifndef _CHECKER
475|#define ThreeD_Vect_getDirLen( a, b ) \
476| ( (a)->x * (b)->x + (a)->y * (b)->y + (a)->z * (b)->z )
477|#endif
478|
479|
480|
481|/*************************************************************************
482|* 24. <<< [ThreeD_Vect_print] 属性を表示する >>>
483|**************************************************************************/
484|#ifndef ERRORS_CUT_DEBUG_TOOL
485|#define ThreeD_Vect_print( this, title ) \
486| ThreeD_XYZ_print( (ThreeD_XYZ*)(this), (title) )
487|#endif
488|
489|
490|
491|/*************************************************************************
492|* 25. <<< [ThreeD_TwoD_initByPoly] ポリゴンを含む平面を二次元座標として初期化する >>>
493|**************************************************************************/
494|#define ThreeD_TwoD_initByPoly( this, poly ) \
495| ThreeD_TwoD_initByP3( this, (poly)->p_array )
496|
497|
498|#endif /* __THREED_H */
499|
500|