/// <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); }
/// <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!"); } }
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!"); } }
public override void RenderForPicking(PickingEventArgs arg) { if (this.RenderWireframe || this.RenderBody) { base.RenderForPicking(arg); } }
/// <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!"); } }
/// <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!"); } }
/// <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!"); } }
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); }
/// <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); }
/// <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!"); } }
/// <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!"); } }
/// <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); }
/// <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); }
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); }
/// <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); }
/// <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); }
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); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); }
/// <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); }
/// <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); }