#ifndef GGAFLIB_STGUTIL_H_
#define GGAFLIB_STGUTIL_H_
#include "GgafLibCommonHeader.h"
#include "jp/ggaf/dxcore/util/GgafDxUtil.h"

#include "jp/ggaf/lib/util/ColliAABox.h"
#include "jp/ggaf/dxcore/actor/GgafDxGeometricActor.h"

#ifdef UTIL
    #undef UTIL
#endif
#define UTIL GgafLib::StgUtil

namespace GgafLib {

/**
 * ユーティリティ .
 * @version 1.00
 * @since 2008/09/08
 * @author Masatoshi Tsuge
 */
class StgUtil: public GgafDxCore::GgafDxUtil {
public:

    static bool _was_StgUtil_inited_flg;

    static void init();

    /**
     * 半径 1000 の 1/4 円の解テーブル .
     * <pre><code>
     *      ______________
     * y = √(1000^2-x^2)
     * </code></pre>
     * の 要素[x] に対する y
     */
    static float ROOT_1_MINUS_XX[1000];

    static uint32_t BITNUM[];

    static GgafDxCore::GgafDxChecker* createChecker(GgafDxCore::GgafDxGeometricActor* prm_pActor);

    static inline bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAABox* const pAABox01,
                             const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox* const pAABox02 ) {
        //＜AAB と AAB＞
        //軸が一致しない確率が高そうな順番(X>Z>Y)に判定
        if (pActor01->_x + pAABox01->_x2 >= pActor02->_x + pAABox02->_x1) {
            if (pActor01->_x + pAABox01->_x1 <= pActor02->_x + pAABox02->_x2) {
                if (pActor01->_z + pAABox01->_z2 >= pActor02->_z + pAABox02->_z1) {
                    if (pActor01->_z + pAABox01->_z1 <= pActor02->_z + pAABox02->_z2) {
                        if (pActor01->_y + pAABox01->_y2 >= pActor02->_y + pAABox02->_y1) {
                            if (pActor01->_y + pAABox01->_y1 <= pActor02->_y + pAABox02->_y2) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliSphere* const pSphere01 ,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere* const pSphere02 );

    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* pActor01, const ColliAABox*  pAABox01,
                      const GgafDxCore::GgafDxGeometricActor* pActor02, const ColliSphere* pSphere02);

    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPrism* const pAAPrism01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox*   const pAABox02   );


    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPrism* const pAAPrism01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere*  const pSphere02  );


    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPyramid* const pAAPyramid01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox*     const pAABox02     );

    static bool isHit3D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPyramid* const pAAPyramid01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere*    const pSphere02    );


    static inline bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAABox* const pAABox01,
                             const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox* const pAABox02 ) {
        //＜AAB と AAB＞
        //軸が一致しない確率が高そうな順番(X>Z>Y)に判定
        if (pActor01->_x + pAABox01->_x2 >= pActor02->_x + pAABox02->_x1) {
            if (pActor01->_x + pAABox01->_x1 <= pActor02->_x + pAABox02->_x2) {
                if (pActor01->_y + pAABox01->_y2 >= pActor02->_y + pAABox02->_y1) {
                    if (pActor01->_y + pAABox01->_y1 <= pActor02->_y + pAABox02->_y2) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliSphere* const pSphere01 ,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere* const pSphere02 );

    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* pActor01, const ColliAABox*  pAABox01,
                      const GgafDxCore::GgafDxGeometricActor* pActor02, const ColliSphere* pSphere02);

    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPrism* const pAAPrism01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox*   const pAABox02   ) {
        return false;
    }


    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPrism* const pAAPrism01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere*  const pSphere02  ) {
        return false;
    }


    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPyramid* const pAAPyramid01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliAABox*     const pAABox02     ) {
        return false;
    }

    static bool isHit2D(const GgafDxCore::GgafDxGeometricActor* const pActor01, const ColliAAPyramid* const pAAPyramid01,
                      const GgafDxCore::GgafDxGeometricActor* const pActor02, const ColliSphere*    const pSphere02    ) {
        return false;
    }

    /**
     * 単発弾を複数個撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_x               発射元X座標
     * @param prm_y               発射元Y座標
     * @param prm_z               発射元Z座標
     * @param prm_rz              発射方向Rz
     * @param prm_ry              発射方向Ry
     * @param prm_pDepo_shot      発射するショットのデポジトリ
     * @param prm_r               発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_velo_first      初弾のショット初期速度
     * @param prm_acce            初弾のショット初期加速度
     * @param prm_set_num         撃つ弾の合計数
     * @param prm_interval_frames 弾と弾の出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全弾一斉発射。）
     * @param prm_attenuated      初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched 弾がデポジトリから dispach() された時に呼び出すコールバック。
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay001(coord prm_x, coord prm_y, coord prm_z,
                                                     angle prm_rz, angle prm_ry,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int) = nullptr);

    /**
     * 発射元が向いている方向（_rz > _ry）に向かって 単発弾を複数個撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_from_x          発射元X座標
     * @param prm_from_y          発射元Y座標
     * @param prm_from_z          発射元Z座標
     * @param prm_to_x            目標X座標
     * @param prm_to_y            目標Y座標
     * @param prm_to_z            目標Z座標
     * @param prm_pDepo_shot      発射するショットのデポジトリ
     * @param prm_r               発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_velo_first      初弾のショット初期速度。初弾以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce            ショット初期加速度
     * @param prm_set_num         撃つ弾の合計数
     * @param prm_interval_frames 弾と弾の出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全弾一斉発射。）
     * @param prm_attenuated      初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay001(coord prm_from_x, coord prm_from_y, coord prm_from_z,
                                                     coord prm_to_x, coord prm_to_y, coord prm_to_z,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int) = nullptr);

    /**
     * 発射元が向いている方向（_rz > _ry）に向かって 単発弾を複数個撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_pFrom           発射元
     * @param prm_pDepo_shot      発射するショットのデポジトリ
     * @param prm_r               発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_velo_first      初弾のショット初期速度。初弾以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce            ショット初期加速度
     * @param prm_set_num         撃つ弾の合計数
     * @param prm_interval_frames 弾と弾の出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全弾一斉発射。）
     * @param prm_attenuated      初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay001(const GgafDxCore::GgafDxGeometricActor* prm_pFrom,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int) = nullptr);


    /**
     * N-Way弾（Rz変化）を複数セット撃つ .
     * prm_rx, prm_rz, prm_ry = (0,0,0) で、XY平面上にRz変化の N-Way弾 を放ちます。
     * @param prm_x                発射元X座標
     * @param prm_y                発射元Y座標
     * @param prm_z                発射元Z座標
     * @param prm_rx               N Wayの回転角
     * @param prm_rz               発射方向Rz
     * @param prm_ry               発射方向Ry
     * @param prm_pDepo_shot       発射するショットのデポジトリ
     * @param prm_r                発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_way_N            N-Way数（Rz変化）
     * @param prm_ang_clearance_N  N-Wayの間隔角度
     * @param prm_velo_first       N-Way弾初弾セットのショット初期速度。初弾セット以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce             N-Way弾各セットのショット初期加速度
     * @param prm_set_num          発射する N-Way弾セットの合計セット数
     * @param prm_interval_frames  弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated       初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay002(coord prm_x, coord prm_y, coord prm_z,
                                                     angle prm_rx, angle prm_rz, angle prm_ry,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     int prm_way_N,
                                                     angle prm_ang_clearance_N,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int) = nullptr);

    /**
     * 発射元が向いている方向（_rx, _rz > _ry）N-Way弾（Rz変化）を複数セット撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_pFrom                  発射元
     * @param prm_pDepo_shot             発射するショットのデポジトリ
     * @param prm_r                      発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_way_N                  N-Way数（Rz変化）
     * @param prm_ang_clearance_N        N-Wayの間隔角度
     * @param prm_velo_first             N-Way弾初弾セットのショット初期速度。初弾セット以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce                   N-Way弾各セットのショット初期加速度
     * @param prm_set_num                発射する N-Way弾セットの合計セット数
     * @param prm_interval_frames        弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated             初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay002(const GgafDxCore::GgafDxGeometricActor* prm_pFrom,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     int prm_way_N,
                                                     angle prm_ang_clearance_N,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int) = nullptr);

    /**
     * N*M-Way弾を複数セット撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_x                発射元X座標
     * @param prm_y                発射元Y座標
     * @param prm_z                発射元Z座標
     * @param prm_rx               N*M 長方形の回転角
     * @param prm_rz               発射方向Rz
     * @param prm_ry               発射方向Ry
     * @param prm_pDepo_shot1      発射するショットのデポジトリその１
     * @param prm_paUint32_dotmat1 ショットその１を使用するドットマトリックス
     * @param prm_pDepo_shot2      発射するショットのデポジトリその２
     * @param prm_paUint32_dotmat2 ショットその２を使用するドットマトリックス
     * @param prm_pDepo_shot3      発射するショットのデポジトリその３
     * @param prm_paUint32_dotmat3 ショットその３を使用するドットマトリックス
     * @param prm_r                発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_way_N            N-Way数（Rz変化）
     * @param prm_way_M            M-Way数（Ry変化）
     * @param prm_ang_clearance_N   N-Wayの間隔角度
     * @param prm_ang_clearance_M   M-Wayの間隔角度
     * @param prm_velo_first       N*M-Way弾初弾セットのショット初期速度。初弾セット以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce             N*M-Way弾各セットのショット初期加速度
     * @param prm_set_num          発射する N*M-Way弾セットの合計セット数
     * @param prm_interval_frames  弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated       初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay003(coord prm_x, coord prm_y, coord prm_z,
                                                     angle prm_rx, angle prm_rz, angle prm_ry,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot1, uint32_t* prm_paUint32_dotmat1,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot2, uint32_t* prm_paUint32_dotmat2,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot3, uint32_t* prm_paUint32_dotmat3,
                                                     coord prm_r,
                                                     int prm_way_N, int prm_way_M,
                                                     angle prm_ang_clearance_N, angle prm_ang_clearance_M,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int, int, int) = nullptr);


    /**
     * 発射元が向いている方向（_rx > _rz > _ry）に向かって N*M-Way弾を複数セット撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_pFrom            発射元
     * @param prm_pDepo_shot1      発射するショットのデポジトリその１
     * @param prm_paUint32_dotmat1 ショットその１を使用するドットマトリックス
     * @param prm_pDepo_shot2      発射するショットのデポジトリその２
     * @param prm_paUint32_dotmat2 ショットその２を使用するドットマトリックス
     * @param prm_pDepo_shot3      発射するショットのデポジトリその３
     * @param prm_paUint32_dotmat3 ショットその３を使用するドットマトリックス
     * @param prm_r                発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_way_N            N-Way数（Rz変化）
     * @param prm_way_M            M-Way数（Ry変化）
     * @param prm_ang_clearance_N  N-Wayの間隔角度
     * @param prm_ang_clearance_M  M-Wayの間隔角度
     * @param prm_velo_first       N*M-Way弾初弾セットのショット初期速度。初弾セット以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce             N*M-Way弾各セットのショット初期加速度
     * @param prm_set_num          発射する N*M-Way弾セットの合計セット数
     * @param prm_interval_frames  弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated       初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay003(const GgafDxCore::GgafDxGeometricActor* prm_pFrom,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot1, uint32_t* prm_paUint32_dotmat1,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot2, uint32_t* prm_paUint32_dotmat2,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot3, uint32_t* prm_paUint32_dotmat3,
                                                     coord prm_r,
                                                     int prm_way_N, int prm_way_M,
                                                     angle prm_ang_clearance_N, angle prm_ang_clearance_M,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int, int, int) = nullptr);

    /**
     * 拡散放射状弾を複数セット同時に撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_x               発射元X座標
     * @param prm_y               発射元Y座標
     * @param prm_z               発射元Z座標
     * @param prm_rz              発射方向Rz
     * @param prm_ry              発射方向Ry
     * @param prm_pDepo_shot      発射するショットのデポジトリ
     * @param prm_r               発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_radial_way_num  １セット放射状Way数
     * @param prm_expanse_angle   発射方向への放射状弾の照射角(0 ～ D180ANG。懐中電灯の光の広がり角のようなイメージ。小さいと弾の間隔が狭い)
     * @param prm_velo_first      初弾セットのショット初期速度。初弾セット以降の初期速度は prm_attenuated を乗じていく。
     * @param prm_acce            各セットのショット初期加速度
     * @param prm_set_num         撃つ放射状WAY弾の合計セット数
     * @param prm_interval_frames 弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated      初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched デポジトリ(prm_pDepo_shot)から dispatch() されて、
     *                                 移動方向、初期速度、加速度が設定された後にコールバックされる関数を設定。
     *                                 引数には次の値が引き渡される。
     *                                 void f(GgafDxCore::GgafDxFigureActor* prm_pActor, int prm_dispatch_num, int prm_set_index, int prm_way_index)
     *                                 prm_pActor         dispatch()された弾のアクター
     *                                 prm_dispatch_num   何回目の dispatch() の弾か  (1～)
     *                                 prm_set_index      放射状WAY弾何セット目であるか (0～)
     *                                 prm_way_index      何WAY目の弾であるか         (0～)
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay004(coord prm_x, coord prm_y, coord prm_z,
                                                     angle prm_rz, angle prm_ry,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     int prm_radial_way_num, angle prm_expanse_angle,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int) = nullptr);

    /**
     * 発射元が向いている方向（_rz > _ry）に向かって拡散放射状弾を複数セット同時に撃つ .
     * 発射するショットに、次の項目が設定されます。<BR>
     * ・ショットの _x, _y, _z 座標 <BR>
     * ・ショットの GgafDxKuroko の移動方向、移動速度、加速度<BR>
     * @param prm_pFrom           発射元
     * @param prm_pDepo_shot      発射するショットのデポジトリ
     * @param prm_r               発射元と発射するショットの初期表示位置距離(発射元からの半径)。0より大きい値の必要有り。
     * @param prm_radial_way_num  １セット放射状Way数
     * @param prm_expanse_angle   発射方向への放射状弾の照射中心角(0 ～ D180ANG。懐中電灯の光の広がりの成す角のようなイメージ。小さいと弾の間隔が狭い)
     * @param prm_velo_first      初弾セットのショット初期速度
     * @param prm_acce            初弾セットのショット初期加速度
     * @param prm_set_num         撃つ放射状WAY弾の合計セット数
     * @param prm_interval_frames 弾セットと弾セットの出現フレーム間隔。(0より大きい設定値で、時間差打ち返しのような演出になる。0 指定は全セット一斉発射。）
     * @param prm_attenuated      初弾セット以降のセット毎のショット初期速度へ乗率。速度減衰(< 1.0)或いは速度増加(>1.0)。1.0は全セット速度が同じ。
     * @param pFunc_call_back_dispatched デポジトリ(prm_pDepo_shot)から dispatch() されて、
     *                                 移動方向、初期速度、加速度が設定された後にコールバックされる関数を設定。
     *                                 引数には次の値が引き渡される。
     *                                 void f(GgafDxCore::GgafDxFigureActor* prm_pActor, int prm_dispatch_num, int prm_set_index, int prm_way_index)
     *                                 prm_pActor         dispatch()された弾のアクター
     *                                 prm_dispatch_num   何回目の dispatch() の弾か  (1～)
     *                                 prm_set_index      放射状WAY弾何セット目であるか (0～)
     *                                 prm_way_index      何WAY目の弾であるか         (0～)
     * @return 最後の発射弾のアクター(撃てなかった場合は nullptr)
     */
    static GgafDxCore::GgafDxFigureActor* shotWay004(const GgafDxCore::GgafDxGeometricActor* prm_pFrom,
                                                     GgafCore::GgafActorDepository* prm_pDepo_shot,
                                                     coord prm_r,
                                                     int prm_radial_way_num, angle prm_expanse_angle,
                                                     velo prm_velo_first, acce prm_acce,
                                                     int prm_set_num, frame prm_interval_frames, float prm_attenuated,
                                                     void (*pFunc_call_back_dispatched)(GgafDxCore::GgafDxFigureActor*, int, int, int) = nullptr);


};

}
#endif /*GGAFLIB_STGUTIL_H_*/



//ピラミッドと球
//  平面 a*x + b*y + c*z + d = 0
//  点D(x0,y0,z0)
//  点から平面に下ろした足の根元を点H(x,y,z) とすると
//
//  ベクトル HD=(x0-x ,y0-y, z0-z) = t(a,b,c)  (tは実数)  ・・・①
//
//  ①より
//  x0 - x = t*a
//  y0 - y = t*b
//  z0 - z = t*c
//  なので
//  x = x0 - t*a
//  y = y0 - t*b
//  z = z0 - t*c
//
//  を平面の式へ代入
//  a*(x0-t*a) + b*(y0-t*b) + c*(z0-t*c) + d = 0
//
//  これをtについて解くと
//  t = (a*x0+b*y0+c*z0+d)/(a^2+b^2+c^2)  ・・・②
//
//  よって
//  x =  x0 - t*a
//    =  x0 - ((a*x0+b*y0+c*z0+d)/(a^2+b^2+c^2))*a
//
//  y = y0 - t*b
//    = y0 - ((a*x0+b*y0+c*z0+d)/(a^2+b^2+c^2))*b
//
//  z = z0 - t*c
//    = z0 - ((a*x0+b*y0+c*z0+d)/(a^2+b^2+c^2))*c
//
//  また、HDの距離は
//  |HD|= |t(a,b,c)| = |t|*|(a,b,c)| = abs(t)*sqrt(a^2+b^2+c^2)  ・・・③
//
//  ②のtを③へ代入
//
//  |HD| = abs((c*z0+b*y0+a*x0+d)/(c^2+b^2+a^2))*sqrt(a^2+b^2+c^2)
//
//  |HD| = abs(a*x0+b*y0+c*z0+d) / sqrt(a^2+b^2+c^2)






//// 特定の点(a,b,c)を通り、方向ベクトルが(p,q,r)の直線は。
//(x,y,z) = (a,b,c) + t(p,q,r)  (tは媒介変数)
//
//x = a + t*p ・・・ ①
//y = b + t*q ・・・ ②
//z = c + t*r ・・・ ③
//
//t = (x-a) /p = (y-b)/q = (z-c)/r
//
//
//点D(x0,y0,z0)
//点から直線に下ろした足の根元を点H(x,y,z) とすると
//ベクトル HD = (x0-x,y0-y, z0-z)
//    = (x0-(a+t*p), y0-(b+t*q), z0-(c+t*r))  ・・・④
//
//これが、(p,q,r) と直交するので、内積=0
//(x0-(a+t*p), y0-(b+t*q), z0-(c+t*r))・(p,q,r) = 0
//p*(x0-(a+t*p)) + q*(y0-(b+t*q)) + r*(z0-(c+t*r)) = 0
//
//tについて解くと
//
//t=(r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2)
//
//④のt に代入し、したがって HD は
//HD = ( x0-(a+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*p),
//y0-(b+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*q),
//z0-(c+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*r)    )
//
//|HD| = sqrt( (x0-(a+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*p))^2 +
//     (y0-(b+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*q))^2 +
//     (z0-(c+( (r*z0+q*y0+p*x0-c*r-b*q-a*p)/(r^2+q^2+p^2) )*r))^2   )
//
//|HD| = sqrt((q^2+p^2)*z0^2+(-2*q*r*y0-2*p*r*x0+(2*b*q+2*a*p)*r-2*c*q^2-2*c*p^2)*z0+(r^2+p^2)*y0^2+
//(-2*p*q*x0-2*b*r^2+2*c*q*r+2*a*p*q-2*b*p^2)*y0+(r^2+q^2)*x0^2+(-2*a*r^2+2*c*p*r-2*a*q^2+2*b*p*q)*x0+(b^2+a^2)*r^2+
//(-2*b*c*q-2*a*c*p)*r+(c^2+a^2)*q^2-2*a*b*p*q+(c^2+b^2)*p^2)/(sqrt(r^2+q^2+p^2))





//// 点 A(a,b,c) B(d,e,f) を通る直線は
//AB = (d-a, e-b, f-c)
//(x,y,z) = (a,b,c) + t(d-a, e-b, f-c)  (tは媒介変数)
//
//x = a + t*(d-a) ・・・ ①
//y = b + t*(e-b) ・・・ ②
//z = c + t*(f-c) ・・・ ③
//
//点D(x0,y0,z0)
//点から直線に下ろした足の根元を点H(x,y,z) とすると
//ベクトル HD = (x0-x,y0-y, z0-z)
//            = (x0-(a+t*(d-a)), y0-(b+t*(e-b)), z0-(c+t*(f-c)))  ・・・④
//
//
//これが、AB=(d-a, e-b, f-c) と直交するので、内積=0
//(x0-(a+t*(d-a)), y0-(b+t*(e-b)), z0-(c+t*(f-c)))・(d-a, e-b, f-c) = 0
//なので
//(x0-(a+t*(d-a)))*(d-a) + (y0-(b+t*(e-b)))*(e-b) + (z0-(c+t*(f-c)))*(f-c) = 0
//
//tについて解くと
//
//t = ((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2)
//
//④の t に代入し、したがって HD は
//HD = ( x0-(a+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(d-a)) ,
//       y0-(b+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(e-b)) ,
//       z0-(c+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(f-c))   )
//
//|HD| = sqrt( (x0-(a+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(d-a)))^2 +
//             (y0-(b+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(e-b)))^2 +
//             (z0-(c+(((f-c)*z0+(e-b)*y0+(d-a)*x0-c*f-b*e-a*d+c^2+b^2+a^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))*(f-c)))^2    )
//
//=sqrt(((e^2-2*b*e+d^2-2*a*d+b^2+a^2)*z0^2+(((2*b-2*e)*f+2*c*e-2*b*c)*y0+((2*a-2*d)*f+2*c*d-2*a*c)*x0+
//(2*b*e+2*a*d-2*b^2-2*a^2)*f-2*c*e^2+2*b*c*e-2*c*d^2+2*a*c*d)*z0+(f^2-2*c*f+d^2-2*a*d+c^2+a^2)*y0^2+
//(((2*a-2*d)*e+2*b*d-2*a*b)*x0-2*b*f^2+(2*c*e+2*b*c)*f+(2*a*d-2*c^2-2*a^2)*e-2*b*d^2+2*a*b*d)*y0+
//(f^2-2*c*f+e^2-2*b*e+c^2+b^2)*x0^2+(-2*a*f^2+(2*c*d+2*a*c)*f-2*a*e^2+(2*b*d+2*a*b)*e+(-2*c^2-2*b^2)*d)*x0+(b^2+a^2)*
//f^2+(-2*b*c*e-2*a*c*d)*f+(c^2+a^2)*e^2-2*a*b*d*e+(c^2+b^2)*d^2)/(f^2-2*c*f+e^2-2*b*e+d^2-2*a*d+c^2+b^2+a^2))












//点 A(x1,y2,z1) B(x2,y1,z1) を通る直線と点D(o_scx,o_scy,o_scz)の距離
//
//(x1,y2,z1) (x2,y1,z1)     (o_scx,o_scy,o_scz)
//
//sqrt(((y1^2-2*y2*y1+x2^2-2*x1*x2+y2^2+x1^2)*o_scz^2+(((2*y2-2*y1)*z1+2*z1*y1-2*y2*z1)*o_scy+((2*x1-2*x2)*z1+2*z1*x2-2*x1*z1)*o_scx+
//(2*y2*y1+2*x1*x2-2*y2^2-2*x1^2)*z1-2*z1*y1^2+2*y2*z1*y1-2*z1*x2^2+2*x1*z1*x2)*o_scz+(z1^2-2*z1*z1+x2^2-2*x1*x2+z1^2+x1^2)*o_scy^2+
//(((2*x1-2*x2)*y1+2*y2*x2-2*x1*y2)*o_scx-2*y2*z1^2+(2*z1*y1+2*y2*z1)*z1+(2*x1*x2-2*z1^2-2*x1^2)*y1-2*y2*x2^2+2*x1*y2*x2)*o_scy+
//(z1^2-2*z1*z1+y1^2-2*y2*y1+z1^2+y2^2)*o_scx^2+(-2*x1*z1^2+(2*z1*x2+2*x1*z1)*z1-2*x1*y1^2+(2*y2*x2+2*x1*y2)*y1+(-2*z1^2-2*y2^2)*x2)*o_scx+(y2^2+x1^2)*
//z1^2+(-2*y2*z1*y1-2*x1*z1*x2)*z1+(z1^2+x1^2)*y1^2-2*x1*y2*x2*y1+(z1^2+y2^2)*x2^2)/(z1^2-2*z1*z1+y1^2-2*y2*y1+x2^2-2*x1*x2+z1^2+y2^2+x1^2))
//
//
//sqrt(((y2^2-2*y1*y2+y1^2+x2^2-2*x1*x2+x1^2)*z1^2+(-2*o_scz*y2^2+4*o_scz*y1*y2-2*o_scz*y1^2-2*o_scz*x2^2+4*o_scz*x1*x2-2*o_scz*x1^2)*z1+
//(x2^2-2*o_scx*x2+o_scz^2+o_scx^2)*y2^2+
//(((2*o_scx-2*x1)*x2+2*o_scx*x1-2*o_scz^2-2*o_scx^2)*y1-2*o_scy*x2^2+(2*o_scy*x1+2*o_scx*o_scy)*x2-2*o_scx*o_scy*x1)*y2+
//(x1^2-2*o_scx*x1+o_scz^2+o_scx^2)*y1^2+((2*o_scy*x1-2*o_scx*o_scy)*x2-2*o_scy*x1^2+2*o_scx*o_scy*x1)*y1+(o_scz^2+o_scy^2)*x2^2+(-2*o_scz^2-2*o_scy^2)*x1*
//x2+(o_scz^2+o_scy^2)*x1^2)/(y2^2-2*y1*y2+y1^2+x2^2-2*x1*x2+x1^2))
//
//
//
//
//t=((z1-z1)*z0+(y1-y2)*y0+(x2-x1)*x0-z1*z1-y2*y1-x1*x2+z1^2+y2^2+x1^2)/(z1^2-2*z1*z1+y1^2-2*y2*y1+x2^2-2*x1*x2+z1^2+y2^2+x1^2)
//
//t=(y2^2+(-y1-y0)*y2+y0*y1+(x0-x1)*x2+x1^2-x0*x1)/(y2^2-2*y1*y2+y1^2+x2^2-2*x1*x2+x1^2)
