/// <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="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="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!"); } }
internal override uint Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { ZeroIndexBufferPtr zeroIndexBufferPtr = modernRenderer.IndexBufferPtr; ZeroIndexBufferPtr indexBufferPtr = null; // when the temp index buffer could be long, it's no longer needed. // what a great OpenGL API design! using (var buffer = new ZeroIndexBuffer(DrawMode.Points, zeroIndexBufferPtr.FirstVertex, zeroIndexBufferPtr.VertexCount)) { indexBufferPtr = buffer.GetBufferPtr() as ZeroIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); if (zeroIndexBufferPtr.FirstVertex <= id && id < zeroIndexBufferPtr.FirstVertex + zeroIndexBufferPtr.VertexCount) { 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="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!"); } }
/// <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> /// 在三角形图元中拾取指定位置的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!"); } }
internal override uint[] Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer <uint>(DrawMode.Lines, BufferUsage.StaticDraw)) { buffer.Create(8); unsafe { var array = (uint *)buffer.Header.ToPointer(); array[0] = lastVertexId - 1; array[1] = lastVertexId - 0; array[2] = lastVertexId - 2; array[3] = lastVertexId - 1; array[4] = lastVertexId - 3; array[5] = lastVertexId - 2; array[6] = lastVertexId - 0; array[7] = lastVertexId - 3; } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); if (id + 3 == lastVertexId) { return(new uint[] { id + 3, id, }); } else { return(new uint[] { id - 1, id, }); } }
internal override uint[] Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { ZeroIndexBufferPtr zeroIndexBufferPtr = modernRenderer.IndexBufferPtr; ZeroIndexBufferPtr indexBufferPtr = null; // when the temp index buffer could be long, it's no longer needed. // what a great OpenGL API design! using (var buffer = new ZeroIndexBuffer(DrawMode.LineLoop, zeroIndexBufferPtr.FirstVertex, zeroIndexBufferPtr.VertexCount)) { indexBufferPtr = buffer.GetBufferPtr() as ZeroIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); if (id == zeroIndexBufferPtr.FirstVertex) { return(new uint[] { (uint)(zeroIndexBufferPtr.FirstVertex + zeroIndexBufferPtr.VertexCount - 1), id, }); } else { return(new uint[] { id - 1, id, }); } }
/// <summary> /// /// </summary> /// <param name="arg"></param> /// <param name="x">mouse position(Left Down is (0, 0)).</param> /// <param name="y">mouse position(Left Down is (0, 0)).</param> /// <param name="lastVertexId"></param> /// <param name="modernRenderer"></param> /// <returns></returns> internal override uint Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { OneIndexBuffer buffer = GLBuffer.Create(IndexBufferElementType.UInt, 3, DrawMode.Points, BufferUsage.StaticDraw); unsafe { var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly); array[0] = 0; array[1] = lastVertexId - 1; array[2] = lastVertexId - 0; buffer.UnmapBuffer(); } modernRenderer.Render4InnerPicking(arg, buffer); uint id = ColorCodedPicking.ReadStageVertexId(x, y); buffer.Dispose(); if (0 == id || lastVertexId - 1 == id || lastVertexId - 0 == id) { return(id); } else { throw new Exception("This should not happen!"); } }
/// <summary> /// /// </summary> /// <param name="arg"></param> /// <param name="x">mouse position(Left Down is (0, 0)).</param> /// <param name="y">mouse position(Left Down is (0, 0)).</param> /// <param name="primitiveInfo"></param> /// <param name="modernRenderer"></param> /// <returns></returns> internal override uint Search(RenderEventArgs arg, int x, int y, RecognizedPrimitiveInfo primitiveInfo, OneIndexRenderer modernRenderer) { uint[] indexList = primitiveInfo.VertexIds; if (indexList.Length < 3) { throw new ArgumentException(); } OneIndexBuffer buffer = indexList.GenIndexBuffer(DrawMode.Points, BufferUsage.StaticDraw); modernRenderer.Render4InnerPicking(arg, buffer); uint id = ColorCodedPicking.ReadStageVertexId(x, y); buffer.Dispose(); if (id != uint.MaxValue) { return(id); } else { throw new Exception("This should not happen!"); } }
/// <summary> /// 在三角形图元中拾取指定位置的Point /// </summary> /// <param name="arg">渲染参数</param> /// <param name="x">mouse position(Left Down is (0, 0)).</param> /// <param name="y">mouse position(Left Down is (0, 0)).</param> /// <param name="lastVertexId">三角形图元的最后一个顶点</param> /// <param name="modernRenderer">目标Renderer</param> /// <returns></returns> internal override uint Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { // 创建临时索引 OneIndexBuffer buffer = Buffer.Create(IndexBufferElementType.UInt, 3, DrawMode.Points, BufferUsage.StaticDraw); unsafe { var array = (uint *)buffer.MapBuffer(MapBufferAccess.WriteOnly); array[0] = lastVertexId - 0; array[1] = lastVertexId - 1; array[2] = lastVertexId - 2; buffer.UnmapBuffer(); } // 用临时索引渲染此三角形图元(仅渲染此三角形图元) modernRenderer.Render4InnerPicking(arg, buffer); // id是拾取到的Line的Last Vertex Id uint id = ColorCodedPicking.ReadStageVertexId(x, y); buffer.Dispose(); // 对比临时索引,找到那个Line if (lastVertexId - 2 <= id && id <= lastVertexId - 0) { return(id); } else { throw new Exception("This should not happen!"); } }
internal override uint[] Search(RenderEventArgs arg, int x, int y, RecognizedPrimitiveIndex lastIndexId, OneIndexRenderer modernRenderer) { List <uint> indexList = lastIndexId.IndexIdList; if (indexList.Count < 3) { throw new ArgumentException(); } OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer <uint>(DrawMode.LineLoop, BufferUsage.StaticDraw)) { buffer.Create(indexList.Count); unsafe { var array = (uint *)buffer.Header.ToPointer(); for (int i = 0; i < indexList.Count; i++) { array[i] = indexList[i]; } } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); if (id == indexList[0]) { return(new uint[] { indexList[indexList.Count - 1], id, }); } else { uint[] result = null; for (int i = 1; i < indexList.Count; i++) { if (id == indexList[i]) { result = new uint[] { indexList[i - 1], indexList[i], }; break; } } if (result != null) { return(result); } else { throw new Exception("This should not happen!"); } } }
internal override uint Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer <uint>(DrawMode.Points, BufferUsage.StaticDraw)) { buffer.Create(3); unsafe { var array = (uint *)buffer.Header.ToPointer(); array[0] = lastVertexId - 0; array[1] = lastVertexId - 1; array[2] = lastVertexId - 2; } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); 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="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!"); } }
/// <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> /// /// </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); }
private uint Pick(RenderEventArgs arg, OneIndexBufferPtr twoPrimitivesIndexBufferPtr, int x, int y) { Render4InnerPicking(arg, twoPrimitivesIndexBufferPtr); uint pickedIndex = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); return(pickedIndex); }
/// <summary> /// /// </summary> /// <param name="arg"></param> /// <param name="twoPrimitivesIndexBuffer"></param> /// <param name="x">mouse position(Left Down is (0, 0)).</param> /// <param name="y">mouse position(Left Down is (0, 0)).</param> /// <returns></returns> private uint Pick(RenderEventArgs arg, OneIndexBuffer twoPrimitivesIndexBuffer, int x, int y) { Render4InnerPicking(arg, twoPrimitivesIndexBuffer); uint pickedIndex = ColorCodedPicking.ReadStageVertexId(x, y); return(pickedIndex); }
internal override uint[] Search(RenderEventArgs arg, int x, int y, RecognizedPrimitiveIndex lastIndexId, OneIndexRenderer modernRenderer) { List <uint> indexList = lastIndexId.IndexIdList; if (indexList.Count != 4) { throw new ArgumentException(); } OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer <uint>(DrawMode.Lines, BufferUsage.StaticDraw)) { buffer.Create(8); unsafe { var array = (uint *)buffer.Header.ToPointer(); array[0] = indexList[0]; array[1] = indexList[1]; array[2] = indexList[1]; array[3] = indexList[2]; array[4] = indexList[2]; array[5] = indexList[3]; array[6] = indexList[3]; array[7] = indexList[0]; } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, y, arg.CanvasRect.Height); indexBufferPtr.Dispose(); if (id == indexList[1]) { return(new uint[] { indexList[0], indexList[1], }); } else if (id == indexList[2]) { return(new uint[] { indexList[1], indexList[2], }); } else if (id == indexList[3]) { return(new uint[] { indexList[2], indexList[3], }); } else if (id == indexList[0]) { return(new uint[] { indexList[2], indexList[0], }); } else { throw new Exception("This should not happen!"); } }
/// <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); }
internal override uint[] Search(RenderEventArgs arg, int x, int y, RecognizedPrimitiveInfo primitiveInfo, OneIndexRenderer modernRenderer) { uint[] indexList = primitiveInfo.VertexIds; if (indexList.Length != 3) { throw new ArgumentException(); } //if (indexList[0] == indexList[1]) { return new uint[] { indexList[0], indexList[2], }; } //else if (indexList[0] == indexList[2]) { return new uint[] { indexList[0], indexList[1], }; } //else if (indexList[1] == indexList[2]) { return new uint[] { indexList[1], indexList[0], }; } OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer(IndexElementType.UInt, DrawMode.Lines, BufferUsage.StaticDraw)) { buffer.Create(6); unsafe { var array = (uint *)buffer.Header.ToPointer(); array[0] = indexList[0]; array[1] = indexList[1]; array[2] = indexList[1]; array[3] = indexList[2]; array[4] = indexList[2]; array[5] = indexList[0]; } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, arg.CanvasRect.Height - y - 1); indexBufferPtr.Dispose(); if (id == indexList[1]) { return(new uint[] { indexList[0], indexList[1], }); } else if (id == indexList[2]) { return(new uint[] { indexList[1], indexList[2], }); } else if (id == indexList[0]) { return(new uint[] { indexList[2], indexList[0], }); } else { throw new Exception("This should not happen!"); } }
/// <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="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[] vertexIds = primitiveInfo.VertexIds; if (vertexIds.Length < 3) { throw new ArgumentException(); } IndexBuffer buffer = vertexIds.GenIndexBuffer(BufferUsage.StaticDraw); var cmd = new DrawElementsCmd(buffer, DrawMode.LineLoop); picker.Node.Render4InnerPicking(arg, cmd); uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y); buffer.Dispose(); uint baseId = stageVertexId - singleNodeVertexId; if (id == baseId + vertexIds[0]) { return(new uint[] { baseId + vertexIds[vertexIds.Length - 1], id, }); } else { uint[] result = null; for (int i = 1; i < vertexIds.Length; i++) { if (id == baseId + vertexIds[i]) { result = new uint[] { baseId + vertexIds[i - 1], id, }; break; } } if (result != null) { return(result); } else { throw new Exception("This should not happen!"); } } }
internal override uint[] Search(RenderEventArgs arg, int x, int y, uint lastVertexId, ZeroIndexRenderer modernRenderer) { OneIndexBufferPtr indexBufferPtr = null; using (var buffer = new OneIndexBuffer(IndexElementType.UInt, DrawMode.Lines, BufferUsage.StaticDraw)) { buffer.Create(8); unsafe { var array = (uint *)buffer.Header.ToPointer(); array[0] = lastVertexId - 0; array[1] = lastVertexId - 2; array[2] = lastVertexId - 2; array[3] = lastVertexId - 3; array[4] = lastVertexId - 3; array[5] = lastVertexId - 1; array[6] = lastVertexId - 1; array[7] = lastVertexId - 0; } indexBufferPtr = buffer.GetBufferPtr() as OneIndexBufferPtr; } modernRenderer.Render4InnerPicking(arg, indexBufferPtr); uint id = ColorCodedPicking.ReadPixel(x, arg.CanvasRect.Height - y - 1); indexBufferPtr.Dispose(); if (id + 2 == lastVertexId) { return(new uint[] { lastVertexId - 0, lastVertexId - 2, }); } else if (id + 3 == lastVertexId) { return(new uint[] { lastVertexId - 2, lastVertexId - 3 }); } else if (id + 1 == lastVertexId) { return(new uint[] { lastVertexId - 3, lastVertexId - 1, }); } else if (id + 0 == lastVertexId) { return(new uint[] { lastVertexId - 1, lastVertexId - 0, }); } 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[] verttexIds = primitiveInfo.VertexIds; if (verttexIds.Length != 3) { throw new ArgumentException(); } //if (indexList[0] == indexList[1]) { return new uint[] { indexList[0], indexList[2], }; } //else if (indexList[0] == indexList[2]) { return new uint[] { indexList[0], indexList[1], }; } //else if (indexList[1] == indexList[2]) { return new uint[] { indexList[1], indexList[0], }; } var targetVertexIds = new uint[6] { verttexIds[0], verttexIds[1], verttexIds[1], verttexIds[2], verttexIds[2], verttexIds[0], }; IndexBuffer buffer = targetVertexIds.GenIndexBuffer(BufferUsage.StaticDraw); var cmd = new DrawElementsCmd(buffer, DrawMode.Lines); picker.Node.Render4InnerPicking(arg, cmd); uint id = ColorCodedPicking.ReadStageVertexId(arg.X, arg.Y); buffer.Dispose(); uint baseId = stageVertexId - singleNodeVertexId; if (id == baseId + verttexIds[1]) { return(new uint[] { baseId + verttexIds[0], id, }); } else if (id == baseId + verttexIds[2]) { return(new uint[] { baseId + verttexIds[1], id, }); } else if (id == baseId + verttexIds[0]) { return(new uint[] { baseId + verttexIds[2], id, }); } else { throw new Exception("This should not happen!"); } }
/// <summary> /// /// </summary> /// <param name="arg"></param> /// <param name="x">mouse position(Left Down is (0, 0)).</param> /// <param name="y">mouse position(Left Down is (0, 0)).</param> /// <param name="primitiveInfo"></param> /// <param name="modernRenderer"></param> /// <returns></returns> internal override uint[] Search(RenderEventArgs arg, int x, int y, RecognizedPrimitiveInfo primitiveInfo, OneIndexRenderer modernRenderer) { uint[] indexList = primitiveInfo.VertexIds; if (indexList.Length < 3) { throw new ArgumentException(); } OneIndexBuffer buffer = indexList.GenIndexBuffer(DrawMode.LineLoop, BufferUsage.StaticDraw); modernRenderer.Render4InnerPicking(arg, buffer); uint id = ColorCodedPicking.ReadStageVertexId(x, y); buffer.Dispose(); if (id == indexList[0]) { return(new uint[] { indexList[indexList.Length - 1], id, }); } else { uint[] result = null; for (int i = 1; i < indexList.Length; i++) { if (id == indexList[i]) { result = new uint[] { indexList[i - 1], indexList[i], }; break; } } if (result != null) { return(result); } else { throw new Exception("This should not happen!"); } } }