コード例 #1
0
        /// <summary>
        /// uint[]配列のセレクション・バッファを解析して、
        /// SelectionDataのリストに変換する。
        /// </summary>
        /// <param name="selectionBuffer">セレクションモードで得られたセレクション・バッファ</param>
        /// <returns>ヒットしたデータのリスト</returns>
        public static List <SelectionData> ParseSelectionBuffer(uint[] selectionBuffer)
        {
            List <SelectionData> dataList = new List <SelectionData>();
            int i = 0;

            try
            {
                for (i = 0; i < selectionBuffer.Length;)
                {
                    if (selectionBuffer[i] == 0)
                    {
                        break;
                    }

                    SelectionData data = new SelectionData();

                    data.nameStackDepth = (int)selectionBuffer[i++];

                    data.zMin = (double)selectionBuffer[i++] / (double)uint.MaxValue;
                    data.zMax = (double)selectionBuffer[i++] / (double)uint.MaxValue;

                    data.names = new int[data.nameStackDepth];
                    for (int j = 0; j < data.nameStackDepth; ++j)
                    {
                        data.names[j] = (int)selectionBuffer[i++];
                    }

                    dataList.Add(data);
                }
            }
            catch (IndexOutOfRangeException ex)      //selectionBufferの長さが足りないと、IndexOutOfRangeExceptionが発生してここに来る。
                {
                    if (i >= selectionBuffer.Length) // つまり、selectionBufferの長さが足りない
                    {
                        //この場合は、うまく取得できたデータだけを返して、長さが足りない分は無視。
                    }
                    else
                    {   //それ以外は想定外のエラーなので、とりあえずエラーを投げておく。
                        throw new Exception("ParseSelectionBuffer failed.", ex);
                    }
                }
            catch (Exception ex)
            {       //IndexOutOfRangeException以外は想定外のエラーなので、とりあえずエラーを投げておく。
                throw new Exception("ParseSelectionBuffer failed.", ex);
            }
            return(dataList);
        }
コード例 #2
0
        /// <summary>
        /// <para>ヒットしたオブジェクトのリストから、最も遠くにあるオブジェクトを取得する。</para>
        /// <para>リストのカウントが0の場合はnullを返す。</para>
        /// </summary>
        /// <param name="pickedList">ヒットしたオブジェクトのリスト</param>
        /// <returns><para>最も遠くにあるオブジェクト。</para>
        /// <para>pickedListのカウントが0の場合はnullを返す。</para></returns>
        public static SelectionData GetFarthest(List <SelectionData> pickedList)
        {
            if (pickedList == null)
            {
                return(null);
            }

            double        zMax     = double.MinValue;
            SelectionData farthest = null;

            for (int i = 0; i < pickedList.Count; i++)
            {
                if (pickedList[i].zMax > zMax)
                {
                    farthest = pickedList[i];
                }
            }

            return(farthest);
        }
コード例 #3
0
        /// <summary>
        /// <para>ヒットしたオブジェクトのリストから、最も手前にあるオブジェクトを取得する。</para>
        /// <para>リストのカウントが0の場合はnullを返す。</para>
        /// </summary>
        /// <param name="pickedList">ヒットしたオブジェクトのリスト</param>
        /// <returns><para>最も手前にあるオブジェクト。</para>
        /// <para>pickedListのカウントが0の場合はnullを返す。</para></returns>
        public static SelectionData GetNearest(List <SelectionData> pickedList)
        {
            if (pickedList == null)
            {
                return(null);
            }

            double        zMin    = double.MaxValue;
            SelectionData nearest = null;

            for (int i = 0; i < pickedList.Count; i++)
            {
                if (pickedList[i].zMin < zMin)
                {
                    nearest = pickedList[i];
                }
            }

            return(nearest);
        }
コード例 #4
0
        //#######################################


        #region public static List<SelectionData> Pick<T>( ... ) where T : class

        /// <summary>
        /// OpenGLのセレクションモードを利用して、マウスピッキングを行う。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items">対象となるオブジェクトのリスト</param>
        /// <param name="renderingParams">レンダリングパラメータ</param>
        /// <param name="mousePos">ピッキングするウィンドウ座標(左下原点)(double[]{x, y})</param>
        /// <param name="region">ヒットする範囲の幅と高さ(double[]{width, height})</param>
        /// <param name="camera">シーンのカメラ(要プロジェクション設定)</param>
        /// <param name="viewport">シーンのビューポート</param>
        /// <param name="pickChild">trueを指定した場合、子オブジェクト単位でヒットする。
        /// falseの場合は、階層構造のトップのオブジェクトがヒットする。</param>
        /// <param name="pickedMatrixSet">セレクションモードで使用された変換行列。
        /// ただし、Modelviewプロパティには引数cameraによるビューイング変換を表す行列が格納される。</param>
        /// <returns><para>ヒットしたオブジェクトのリスト。</para>
        /// <para>ヒットしたオブジェクトは、SelectionData.itemフィールドに格納されている。</para></returns>
        public static List <SelectionData> Pick <T>(
            IDictionary <int, T> items,
            double[] mousePos, double[] region, Jusin.Camera.CCamera camera, int[] viewport, bool pickChild,
            out TransformMatrixes pickedMatrixSet)
            where T : class
        {
            int err = Gl.glGetError();

            if (err != Gl.GL_NO_ERROR)
            {
                throw new Exception();
            }

            uint[] selectionBuff = new uint[SelectionBufferLength];
            Gl.glSelectBuffer(selectionBuff.Length, selectionBuff);

            Gl.glRenderMode(Gl.GL_SELECT);

            Gl.glInitNames();
            Gl.glPushName(0);

            //マウスピッキング時の変換行列
            //しばしば必要になるので、取得しておく。
            pickedMatrixSet          = new TransformMatrixes();
            pickedMatrixSet.Viewport = viewport;

            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glPushMatrix();
            Gl.glLoadIdentity();

            //プロジェクション行列を取得。
            camera.ApplyProjection();
            double[] current_projection = new double[16];
            Gl.glGetDoublev(Gl.GL_PROJECTION_MATRIX, current_projection);
            pickedMatrixSet.Projection = current_projection;

            //PickMatrixをセットする必要があるので、改めてプロジェクション行列をセット。
            Gl.glLoadIdentity();
            Glu.gluPickMatrix(mousePos[0], mousePos[1], region[0], region[1], viewport);
            Gl.glMultMatrixd(pickedMatrixSet.Projection);

            //モデルビュー行列を設定。
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glPushMatrix();
            Gl.glLoadIdentity();
            camera.gluLookAtLH();

            //モデルビュー行列を取得。
            Gl.glGetDoublev(Gl.GL_MODELVIEW_MATRIX, pickedMatrixSet.Modelview);


            foreach (int key in items.Keys)
            {
                if ((items[key] != null) && (items[key] is ISelectable))
                {
                    ISelectable drawItem = (ISelectable)items[key];
                    if (drawItem.Selectable)
                    {
                        Gl.glLoadName(drawItem.name);
                        drawItem.DrawSceneForSelectionMode(drawItem.name);
                    }
                }
            }    /*
                  * for (int i = 0; i < items.Count; i++)
                  * {
                  *
                  * if ((items[i] != null) && (items[i] is ISelectable))
                  * {
                  *     ISelectable drawItem = (ISelectable)items[i];
                  *     if (drawItem.Selectable)
                  *     {
                  *         Gl.glLoadName(drawItem.name);
                  *         drawItem.DrawSceneForSelectionMode(drawItem.name);
                  *     }
                  * }
                  * }*/

            Gl.glPopName();

            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glPopMatrix();

            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glPopMatrix();

            int hits = Gl.glRenderMode(Gl.GL_RENDER);

            err = Gl.glGetError();
            if (err != Gl.GL_NO_ERROR)
            {
                throw new Exception(err.ToString());
            }

            List <SelectionData> hitData = SelectionData.ParseSelectionBuffer(selectionBuff);

            if (hitData.Count != 0)
            {
                if (pickChild)
                {
                    for (int i = 0; i < hitData.Count; i++)
                    {
                        hitData[i].item = ((ISelectable)items[hitData[i].names[0]]).GettHitObject(hitData[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < hitData.Count; i++)
                    {
                        hitData[i].item = (ISelectable)items[hitData[i].names[0]];
                    }
                }
            }

            return(hitData);
        }