예제 #1
0
        /// <summary>
        /// Pick geometry at specified positon.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="geometryTypes"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public PickedGeometry Pick(int x, int y, PickingGeometryTypes geometryTypes, int width, int height)
        {
            if (x < 0 || width <= x)
            {
                return(null);
            }
            if (y < 0 || height <= y)
            {
                return(null);
            }
            if (geometryTypes == 0)
            {
                return(null);
            }

            PickedGeometry pickedGeometry = null;

            Framebuffer framebuffer = GetPickingFramebuffer(width, height);

            framebuffer.Bind();
            {
                const float one = 1.0f;
                GL.Instance.ClearColor(one, one, one, one);
                GL.Instance.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);

                var arg = new PickingEventArgs(this.Scene, x, y, geometryTypes);
                this.RenderForPicking(this.Scene.RootNode, arg);

                bool dump = false;
                if (dump)
                {
                    var final = new Bitmap(width, height);
                    var data  = final.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    //glGetTexImage((uint)texture.Target, 0, GL_BGRA, GL_UNSIGNED_BYTE, data.Scan0);
                    GL.Instance.ReadPixels(0, 0, width, height, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, data.Scan0);
                    final.UnlockBits(data);
                    final.RotateFlip(RotateFlipType.Rotate180FlipX);
                    final.Save(string.Format("picking.dump.png"));
                }

                uint stageVertexId = ColorCodedPicking.ReadStageVertexId(x, y);

                pickedGeometry = SearchGeometry(stageVertexId, arg, this.Scene.RootNode);

                if (pickedGeometry != null)
                {
                    var      depth  = new float[1];
                    GCHandle pinned = GCHandle.Alloc(depth, GCHandleType.Pinned);
                    IntPtr   header = pinned.AddrOfPinnedObject();
                    // same with: IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
                    GL.Instance.ReadPixels(x, y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, header);
                    pinned.Free();

                    pickedGeometry.PickedPosition = new vec3(x, y, depth[0]);
                }
            }
            framebuffer.Unbind();

            return(pickedGeometry);
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="singleNodeVertexId"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint[] Search(PickingEventArgs arg,
                                        uint singleNodeVertexId, uint stageVertexId, DrawArraysPicker picker)
        {
            var cmd = picker.DrawCommand as DrawArraysCmd;
            // when the temp index buffer could be long, it's no longer needed.
            // what a great OpenGL API design!
            DrawArraysCmd drawCmd = new DrawArraysCmd(DrawMode.LineLoop, cmd.MaxVertexCount, cmd.FirstVertex, cmd.VertexCount);

            picker.Node.Render4InnerPicking(arg, drawCmd);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            uint baseId = stageVertexId - singleNodeVertexId;

            if (id == baseId + cmd.FirstVertex)
            {
                return(new uint[] { (uint)(baseId + cmd.FirstVertex + cmd.VertexCount - 1), id, });
            }
            else if (baseId + cmd.FirstVertex < id && id <= (uint)(baseId + cmd.FirstVertex + cmd.VertexCount - 1))
            {
                return(new uint[] { id - 1, id, });
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #3
0
        private void RenderForPicking(SceneNodeBase sceneElement, PickingEventArgs arg)
        {
            if (sceneElement != null)
            {
                var      pickable = sceneElement as IPickable;
                TwoFlags flags    = (pickable != null) ? pickable.EnablePicking : TwoFlags.None;
                bool     before   = ((flags & TwoFlags.BeforeChildren) == TwoFlags.BeforeChildren);
                bool     children = (pickable == null) || ((flags & TwoFlags.Children) == TwoFlags.Children);

                if (before)
                {
                    pickable.PickingBaseId += arg.RenderedVertexCount;
                    pickable.RenderForPicking(arg);
                    arg.RenderedVertexCount += pickable.GetVertexCount();
                }

                if (children)
                {
                    foreach (var item in sceneElement.Children)
                    {
                        this.RenderForPicking(item, arg);
                    }
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="singleNodeVertexId"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg,
                                      uint singleNodeVertexId, uint stageVertexId, DrawArraysPicker picker)
        {
            var array = new uint[]
            {
                singleNodeVertexId - 0,
                singleNodeVertexId - 1,
                singleNodeVertexId - 2
            };
            IndexBuffer buffer = array.GenIndexBuffer(BufferUsage.StaticDraw);
            var         cmd    = new DrawElementsCmd(buffer, DrawMode.Points);

            picker.Node.Render4InnerPicking(arg, cmd);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            if (stageVertexId - 2 <= id && id <= stageVertexId - 0)
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #5
0
 public override void RenderForPicking(PickingEventArgs arg)
 {
     if (this.RenderWireframe || this.RenderBody)
     {
         base.RenderForPicking(arg);
     }
 }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="lastVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg, uint lastVertexId, ZeroIndexPicker picker)
        {
            OneIndexBuffer buffer = GLBuffer.Create(IndexBufferElementType.UInt, 4, DrawMode.Points, BufferUsage.StaticDraw);

            unsafe
            {
                var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly);
                array[0] = lastVertexId - 0;
                array[1] = lastVertexId - 1;
                array[2] = lastVertexId - 2;
                array[3] = lastVertexId - 3;
                buffer.UnmapBuffer();
            }
            picker.Renderer.Render4InnerPicking(arg, buffer);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();
            if (lastVertexId - 3 <= id && id <= lastVertexId - 0)
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg,
                                      RecognizedPrimitiveInfo primitiveInfo,
                                      DrawElementsPicker picker)
        {
            uint[] indexList = primitiveInfo.VertexIds;
            if (indexList.Length < 3)
            {
                throw new ArgumentException();
            }

            IndexBuffer buffer = indexList.GenIndexBuffer(BufferUsage.StaticDraw);
            var         cmd    = new DrawElementsCmd(buffer, DrawMode.Points);

            picker.Node.Render4InnerPicking(arg, cmd);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            if (id != uint.MaxValue)
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #8
0
        /// <summary>
        /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元,
        /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引,
        /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="lastVertexId"></param>
        /// <returns></returns>
        private List <RecognizedPrimitiveInfo> GetLastIndexIdList(PickingEventArgs arg, uint lastVertexId)
        {
            var drawCmd = this.DrawCommand;
            PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create(
                (arg.GeometryType.Contains(GeometryType.Point) &&
                 drawCmd.Mode.ToGeometryType() == GeometryType.Line) ?
                DrawMode.Points : drawCmd.Mode);

            PrimitiveRestartState glState = GetPrimitiveRestartState();

            var    buffer  = (drawCmd as IHasIndexBuffer).IndexBufferObject;
            IntPtr pointer = buffer.MapBuffer(MapBufferAccess.ReadOnly);
            List <RecognizedPrimitiveInfo> primitiveInfoList = null;

            if (glState == null)
            {
                primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, drawCmd as DrawElementsCmd);
            }
            else
            {
                primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, drawCmd as DrawElementsCmd, glState.RestartIndex);
            }
            buffer.UnmapBuffer();

            return(primitiveInfoList);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="lastVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint[] Search(PickingEventArgs arg,
                                        uint lastVertexId, ZeroIndexPicker picker)
        {
            OneIndexBuffer buffer = GLBuffer.Create(IndexBufferElementType.UInt, 6, DrawMode.Lines, BufferUsage.StaticDraw);

            unsafe
            {
                var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly);
                array[0] = 0; array[1] = lastVertexId - 1;
                array[2] = lastVertexId - 1; array[3] = lastVertexId - 0;
                array[4] = lastVertexId - 0; array[5] = 0;
                buffer.UnmapBuffer();
            }
            picker.Renderer.Render4InnerPicking(arg, buffer);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            if (id + 1 == lastVertexId)
            {
                return(new uint[] { 0, lastVertexId - 1, });
            }
            else if (id == lastVertexId)
            {
                return(new uint[] { lastVertexId - 1, lastVertexId - 0, });
            }
            else if (id == 0)
            {
                return(new uint[] { lastVertexId - 0, 0, });
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #10
0
        private PickedGeometry SearchGeometry(uint stageVertexId, PickingEventArgs arg, SceneNodeBase node)
        {
            PickedGeometry pickedGeometry = null;

            if (node != null)
            {
                var pickable = node as IPickable;
                if (pickable != null)
                {
                    pickedGeometry = pickable.GetPickedGeometry(arg, stageVertexId);
                }

                if (pickedGeometry == null)
                {
                    foreach (var item in node.Children)
                    {
                        pickedGeometry = SearchGeometry(stageVertexId, arg, item);
                        if (pickedGeometry != null)
                        {
                            break;
                        }
                    }
                }
            }

            return(pickedGeometry);
        }
예제 #11
0
        /// <summary>
        /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元,
        /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引,
        /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="lastVertexId"></param>
        /// <returns></returns>
        private List <RecognizedPrimitiveInfo> GetLastIndexIdList(PickingEventArgs arg, uint lastVertexId)
        {
            var indexBuffer = this.Renderer.PickingRenderUnit.VertexArrayObject.IndexBuffer;
            PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create(
                (arg.GeometryType.Contains(GeometryType.Point) &&
                 indexBuffer.Mode.ToGeometryType() == GeometryType.Line) ?
                DrawMode.Points : indexBuffer.Mode);

            PrimitiveRestartState glState = GetPrimitiveRestartState();

            var    buffer  = indexBuffer as OneIndexBuffer;
            IntPtr pointer = buffer.MapBuffer(MapBufferAccess.ReadOnly);
            List <RecognizedPrimitiveInfo> primitiveInfoList = null;

            if (glState == null)
            {
                primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, indexBuffer as OneIndexBuffer);
            }
            else
            {
                primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, indexBuffer as OneIndexBuffer, glState.RestartIndex);
            }
            buffer.UnmapBuffer();

            return(primitiveInfoList);
        }
예제 #12
0
        /// <summary>
        /// 在三角形图元中拾取指定位置的Point
        /// </summary>
        /// <param name="arg">渲染参数</param>
        /// <param name="lastVertexId">三角形图元的最后一个顶点</param>
        /// <param name="picker">目标Renderer</param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg, uint lastVertexId, DrawArraysPicker picker)
        {
            // 创建临时索引
            IndexBuffer buffer = GLBuffer.Create(IndexBufferElementType.UInt, 3, BufferUsage.StaticDraw);

            unsafe
            {
                var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly);
                array[0] = lastVertexId - 0;
                array[1] = lastVertexId - 1;
                array[2] = lastVertexId - 2;
                buffer.UnmapBuffer();
            }
            var cmd = new DrawElementsCmd(buffer, DrawMode.Points);

            // 用临时索引渲染此三角形图元(仅渲染此三角形图元)
            picker.Node.Render4InnerPicking(arg, IndexAccessMode.ByFrame, cmd);
            // id是拾取到的Line的Last Vertex Id
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            // 对比临时索引,找到那个Line
            if (lastVertexId - 2 <= id && id <= lastVertexId - 0)
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="flatColorVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg,
                                      uint flatColorVertexId, DrawArraysPicker picker)
        {
            IndexBuffer buffer = GLBuffer.Create(IndexBufferElementType.UInt, 4, BufferUsage.StaticDraw);

            unsafe
            {
                var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly);
                array[0] = flatColorVertexId - 0;
                array[1] = flatColorVertexId - 1;
                array[2] = flatColorVertexId - 2;
                array[3] = flatColorVertexId - 3;
                buffer.UnmapBuffer();
            }
            var cmd = new DrawElementsCmd(buffer, DrawMode.Points);

            picker.Node.Render4InnerPicking(arg, IndexAccessMode.ByFrame, cmd);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            if (flatColorVertexId - 3 <= id && id <= flatColorVertexId - 0)
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg,
                                      RecognizedPrimitiveInfo primitiveInfo,
                                      OneIndexPicker picker)
        {
            uint[] indexList = primitiveInfo.VertexIds;
            if (indexList.Length != 3)
            {
                throw new ArgumentException();
            }

            OneIndexBuffer buffer = indexList.GenIndexBuffer(DrawMode.Points, BufferUsage.StaticDraw);

            picker.Renderer.Render4InnerPicking(arg, buffer);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            if (id == indexList[0] || id == indexList[1] || id == indexList[2])
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="singleNodeVertexId"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="picker"></param>
        /// <returns></returns>
        internal override uint Search(PickingEventArgs arg,
                                      RecognizedPrimitiveInfo primitiveInfo,
                                      uint singleNodeVertexId, uint stageVertexId,
                                      DrawElementsPicker picker)
        {
            uint[] indexList = primitiveInfo.VertexIds;
            if (indexList.Length != 4)
            {
                throw new ArgumentException();
            }

            IndexBuffer buffer = indexList.GenIndexBuffer(BufferUsage.StaticDraw);
            var         cmd    = new DrawElementsCmd(buffer, DrawMode.Points);

            picker.Node.Render4InnerPicking(arg, cmd);
            uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            buffer.Dispose();

            uint baseId = stageVertexId - singleNodeVertexId;

            if (id == baseId + indexList[0] || id == baseId + indexList[1] ||
                id == baseId + indexList[2] || id == baseId + indexList[3])
            {
                return(id);
            }
            else if (id == uint.MaxValue) // Scene's changed before second rendering for picking>
            {
                return(id);
            }
            else
            {
                throw new Exception("This should not happen!");
            }
        }
예제 #16
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="twoPrimitivesIndexBuffer"></param>
        /// <returns></returns>
        private uint Pick(PickingEventArgs arg, OneIndexBuffer twoPrimitivesIndexBuffer)
        {
            this.Renderer.Render4InnerPicking(arg, twoPrimitivesIndexBuffer);

            uint pickedIndex = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            return(pickedIndex);
        }
예제 #17
0
        /// <summary>
        /// 是三角形,就pick一个三角形;是四边形,就pick一个四边形,是多边形,就pick一个多边形。
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="typeOfMode"></param>
        /// <returns></returns>
        private PickedGeometry PickWhateverItIs(PickingEventArgs arg, uint stageVertexId, RecognizedPrimitiveInfo primitiveInfo, GeometryType typeOfMode)
        {
            uint[] vertexIds      = primitiveInfo.VertexIds;
            vec3[] positions      = FillPickedGeometrysPosition(vertexIds);
            var    pickedGeometry = new PickedGeometry(typeOfMode, positions, vertexIds, stageVertexId, this.Node);

            return(pickedGeometry);
        }
예제 #18
0
        private PickedGeometry PickPoint(PickingEventArgs arg, uint stageVertexId, uint singleNodeVertexId)
        {
            var vertexIds      = new uint[] { singleNodeVertexId, };
            var positions      = FillPickedGeometrysPosition(vertexIds);
            var pickedGeometry = new PickedGeometry(GeometryType.Point, positions, vertexIds, stageVertexId, this.Node);

            return(pickedGeometry);
        }
예제 #19
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="twoPrimitivesIndexBuffer"></param>
        /// <returns></returns>
        private uint Pick(PickingEventArgs arg, DrawElementsCmd twoPrimitivesIndexBuffer)
        {
            this.Node.Render4InnerPicking(arg, ControlMode.ByFrame, twoPrimitivesIndexBuffer);

            uint pickedIndex = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);

            return(pickedIndex);
        }
예제 #20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="lastVertexId"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private PickedGeometry SearchPoint(PickingEventArgs arg, uint stageVertexId, uint lastVertexId, RecognizedPrimitiveInfo primitiveInfo, OneIndexPointSearcher searcher)
        {
            var vertexIds = new uint[] { searcher.Search(arg, primitiveInfo, this), };

            vec3[] positions      = FillPickedGeometrysPosition(vertexIds);
            var    pickedGeometry = new PickedGeometry(GeometryType.Point, positions, vertexIds, stageVertexId, this.Renderer);

            return(pickedGeometry);
        }
예제 #21
0
        private PickedGeometry PickPoint(PickingEventArgs arg, uint stageVertexId, uint lastVertexId)
        {
            var vertexIds = new uint[] { lastVertexId, };

            vec3[] positions      = FillPickedGeometrysPosition(vertexIds);
            var    pickedGeometry = new PickedGeometry(GeometryType.Point, positions, vertexIds, stageVertexId, this.Renderer);

            return(pickedGeometry);
        }
예제 #22
0
        /// <summary>
        /// Search line in triangles/triangle_strip/triangle_fan/
        /// triangles_adjacency/triangle_strip_adjacency/
        /// quads/quad_strip/polygon
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="lastVertexId"></param>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private PickedGeometry SearchLine(PickingEventArgs arg, uint stageVertexId,
                                          uint lastVertexId, ZeroIndexLineSearcher searcher)
        {
            var vertexIds      = searcher.Search(arg, lastVertexId, this);
            var positions      = FillPickedGeometrysPosition(vertexIds);
            var pickedGeometry = new PickedGeometry(GeometryType.Line, positions, vertexIds, stageVertexId, this.Renderer);

            return(pickedGeometry);
        }
예제 #23
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="lastVertexId"></param>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private PickedGeometry SearchPoint(PickingEventArgs arg, uint stageVertexId, uint lastVertexId, DrawArraysPointSearcher searcher)
        {
            var vertexIds = new uint[] { searcher.Search(arg, lastVertexId, this), };

            vec3[] positions      = FillPickedGeometrysPosition(vertexIds);
            var    pickedGeometry = new PickedGeometry(GeometryType.Point, positions, vertexIds, stageVertexId, this.Node);

            return(pickedGeometry);
        }
예제 #24
0
        /// <summary>
        /// Search line in triangles/triangle_strip/triangle_fan/
        /// triangles_adjacency/triangle_strip_adjacency/
        /// quads/quad_strip/polygon
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="singleNodeVertexId"></param>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private PickedGeometry SearchLine(PickingEventArgs arg, uint stageVertexId,
                                          uint singleNodeVertexId, DrawArraysLineSearcher searcher)
        {
            var vertexIds      = searcher.Search(arg, singleNodeVertexId, stageVertexId, this);
            var positions      = FillPickedGeometrysPosition(vertexIds);
            var pickedGeometry = new PickedGeometry(GeometryType.Line, positions, vertexIds, stageVertexId, this.Node);

            return(pickedGeometry);
        }
예제 #25
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <param name="primitiveInfo"></param>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private PickedGeometry SearchLine(PickingEventArgs arg, uint singleNodeVertexId, uint stageVertexId, RecognizedPrimitiveInfo primitiveInfo, DrawElementsLineSearcher searcher)
        {
            var vertexIds = searcher.Search(arg, primitiveInfo, singleNodeVertexId, stageVertexId, this);

            vec3[] positions      = FillPickedGeometrysPosition(vertexIds);
            var    pickedGeometry = new PickedGeometry(GeometryType.Line, positions, vertexIds, stageVertexId, this.Node);

            return(pickedGeometry);
        }
        private void RenderForPicking(PickingEventArgs arg, ControlMode controlMode, IDrawCommand tmpCmd)
        {
            if (!this.IsInitialized)
            {
                this.Initialize();
            }

            this.polygonModeState.Mode = arg.GeometryType.GetPolygonMode();

            ShaderProgram program = this.PickingRenderUnit.Program;

            // 绑定shader
            program.Bind();
            {
                mat4 projection = arg.Scene.Camera.GetProjectionMatrix();
                mat4 view       = arg.Scene.Camera.GetViewMatrix();
                mat4 model      = this.GetModelMatrix();
                program.glUniform("MVP", projection * view * model);
            }

            this.polygonModeState.On();
            this.lineWidthState.On();
            this.pointSizeState.On();

            PrimitiveRestartState restart = null;
            var hasIndexBuffer            = tmpCmd as IHasIndexBuffer;

            if (hasIndexBuffer != null)
            {
                restart = this.GetPrimitiveRestartState(hasIndexBuffer.IndexBufferObject.ElementType);
            }
            if (restart != null)
            {
                restart.On();
            }
            {
                var  pickable = this as IPickable;
                uint baseId   = pickable.PickingBaseId;
                foreach (var vao in this.PickingRenderUnit.VertexArrayObjects)
                {
                    program.glUniform("pickingBaseId", (int)(baseId));
                    vao.Draw(controlMode, tmpCmd);
                    baseId += (uint)vao.VertexAttributes[0].Buffer.Length;
                }
            }
            if (restart != null)
            {
                restart.Off();
            }

            this.pointSizeState.Off();
            this.lineWidthState.Off();
            this.polygonModeState.Off();

            // 解绑shader
            program.Unbind();
        }
예제 #27
0
        /// <summary>
        /// Pick geometry at specified positon.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="pickTriangle"></param>
        /// <param name="pickQuad"></param>
        /// <param name="pickPolygon"></param>
        /// <returns></returns>
        public PickedGeometry Pick(int x, int y, bool pickTriangle, bool pickQuad, bool pickPolygon)
        {
            PickingGeometryTypes geometryTypes = 0;

            if (pickTriangle)
            {
                geometryTypes |= PickingGeometryTypes.Triangle;
            }
            if (pickQuad)
            {
                geometryTypes |= PickingGeometryTypes.Quad;
            }
            if (pickPolygon)
            {
                geometryTypes |= PickingGeometryTypes.Polygon;
            }
            if (geometryTypes == 0)
            {
                return(null);
            }

            PickedGeometry pickedGeometry = null;

            Framebuffer framebuffer = GetPickingFramebuffer();

            framebuffer.Bind();
            {
                const float one = 1.0f;
                GL.Instance.ClearColor(one, one, one, one);
                GL.Instance.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);

                var arg = new PickingEventArgs(this.Scene, x, y, geometryTypes);
                this.RenderForPicking(this.Scene.RootElement, arg);

                uint stageVertexId = ColorCodedPicking.ReadStageVertexId(x, y);

                pickedGeometry = Pick(stageVertexId, arg, this.Scene.RootElement);

                if (pickedGeometry != null)
                {
                    var      depth  = new float[1];
                    GCHandle pinned = GCHandle.Alloc(depth, GCHandleType.Pinned);
                    IntPtr   header = pinned.AddrOfPinnedObject();
                    // same with: IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
                    GL.Instance.ReadPixels(x, y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, header);
                    pinned.Free();

                    pickedGeometry.PickedPosition = new vec3(x, y, depth[0]);
                }
            }
            framebuffer.Unbind();

            return(pickedGeometry);
        }
예제 #28
0
        /// <summary>
        /// 在所有可能的图元(lastVertexId匹配)中,
        /// 逐个测试,找到最接近摄像机的那个图元,
        /// 返回此图元的最后一个索引在<see cref="IndexBuffer"/>中的索引(位置)。
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="primitiveInfoList"></param>
        /// <returns></returns>
        private RecognizedPrimitiveInfo GetLastIndexId(
            PickingEventArgs arg,
            List <RecognizedPrimitiveInfo> primitiveInfoList)
        {
            if (primitiveInfoList == null || primitiveInfoList.Count == 0)
            {
                return(null);
            }
#if DEBUG
            SameLengths(primitiveInfoList);
#endif
            if (primitiveInfoList[0].VertexIds.Length == 1)// picking a point.
            {
                return(primitiveInfoList[0]);
            }

            int target = 0;
#if DEBUG
            NoPrimitiveRestartIndex(primitiveInfoList);
#endif
            DrawMode singlePrimitiveMode = this.DrawCommand.Mode.ToSinglePrimitiveMode();
            for (int left = 0; left < primitiveInfoList.Count - 1; left++)
            {
                for (int right = left + 1; right < primitiveInfoList.Count; right++)
                {
                    DrawElementsCmd twoPrimitivesIndexBuffer;
                    uint            leftLastIndex, rightLastIndex;
                    AssembleIndexBuffer(
                        primitiveInfoList[left], primitiveInfoList[right], singlePrimitiveMode,
                        out twoPrimitivesIndexBuffer, out leftLastIndex, out rightLastIndex);
                    uint pickedIndex = Pick(arg, twoPrimitivesIndexBuffer);
                    if (pickedIndex == rightLastIndex)
                    {
                        target = right;
                        break;
                    }
                    else if (pickedIndex == leftLastIndex)
                    {
                        target = left;
                        break;
                    }
                    else if (pickedIndex == uint.MaxValue) // 两个候选图元都没有被拾取到
                    {                                      /* nothing to do */
                    }
                    else
                    {
                        throw new Exception("This should not happen!");
                    }
                }
            }

            return(primitiveInfoList[target]);
        }
        /// <summary>
        /// 在所有可能的图元(flatColorVertexId匹配)中,
        /// 逐个测试,找到最接近摄像机的那个图元,
        /// 返回此图元的最后一个索引在<see cref="IndexBuffer"/>中的索引(位置)。
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="primitiveInfoList"></param>
        /// <returns></returns>
        private RecognizedPrimitiveInfo FindThePickedOne(
            PickingEventArgs arg,
            List <RecognizedPrimitiveInfo> primitiveInfoList, uint baseId)
        {
            if (primitiveInfoList == null || primitiveInfoList.Count == 0)
            {
                return(null);
            }
#if DEBUG
            SameLengths(primitiveInfoList);
#endif
            if (primitiveInfoList[0].VertexIds.Length == 1)// picking a point.
            {
                return(primitiveInfoList[0]);
            }

            int target = 0;
#if DEBUG
            NoPrimitiveRestartIndex(primitiveInfoList);
#endif
            DrawMode singlePrimitiveMode = this.DrawCommand.CurrentMode.ToSinglePrimitiveMode();
            for (int current = 1; current < primitiveInfoList.Count; current++)
            {
                DrawElementsCmd twoPrimitivesIndexBuffer;
                uint            leftLastIndex, rightLastIndex;
                AssembleIndexBuffer(
                    primitiveInfoList[target], primitiveInfoList[current], singlePrimitiveMode,
                    out twoPrimitivesIndexBuffer, out leftLastIndex, out rightLastIndex);

                this.Node.Render4InnerPicking(arg, twoPrimitivesIndexBuffer);
                uint stageVertexId = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y);
                uint pickedIndex   = stageVertexId - baseId;
                if (pickedIndex == rightLastIndex)
                {
                    target = current;
                }
                else if (pickedIndex == leftLastIndex)// 保留上一次的候选图元
                {
                    //target = target;
                    /* nothing to do */
                }
                else if (stageVertexId == uint.MaxValue) // 两个候选图元都没有被拾取到
                {                                        /* nothing to do */
                }
                else
                {
                    throw new Exception("This should not happen!");
                }
            }

            return(primitiveInfoList[target]);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="stageVertexId"></param>
        /// <returns></returns>
        public virtual PickedGeometry GetPickedGeometry(PickingEventArgs arg, uint stageVertexId)
        {
            PickedGeometry result = null;

            PickerBase picker = this.picker;

            if (picker != null)
            {
                result = picker.GetPickedGeometry(arg, stageVertexId);
            }

            return(result);
        }