<commit_before>﻿using GLM;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpGL
{
    //TODO:  copyed from ModernRenderer, need to update(This is complex)
    public partial class OneIndexModernRenderer
    {

        public override IPickedGeometry Pick(ICamera camera, uint stageVertexID,
            int x, int y, int canvasWidth, int canvasHeight)
        {
            uint lastVertexID;
            PickedGeometry pickedGeometry = null;
            if (this.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
            {
                // 找到 lastIndexID
                RecognizedPrimitiveIndex lastIndexID = this.GetLastIndexIDOfPickedGeometry(
                    camera, lastVertexID, x, y, canvasWidth, canvasHeight);
                // 获取pickedGeometry
                pickedGeometry = this.GetGeometry(lastIndexID, stageVertexID);
            }

            return pickedGeometry;
        }

        private PickedGeometry GetGeometry(RecognizedPrimitiveIndex lastIndexID, uint stageVertexID)
        {
            var pickedGeometry = new PickedGeometry();
            pickedGeometry.GeometryType = this.indexBufferPtr.Mode.ToPrimitiveMode().ToGeometryType();
            pickedGeometry.StageVertexID = stageVertexID;
            pickedGeometry.From = this;
            //TODO: 
            //pickedGeometry.Positions = ?
            pickedGeometry.Indexes = lastIndexID.IndexIDList.ToArray();

            return pickedGeometry;
        }

        private RecognizedPrimitiveIndex GetLastIndexIDOfPickedGeometry(
            ICamera camera,
            uint lastVertexID, int x, int y, int canvasWidth, int canvasHeight)
        {
            List<RecognizedPrimitiveIndex> lastIndexIDList = GetLastIndexIDList(lastVertexID);

            RecognizedPrimitiveIndex lastIndexID = GetLastIndexID(
                camera, lastIndexIDList, x, y, canvasWidth, canvasHeight);

            return lastIndexID;
        }

        /// <summary>
        /// 在所有可能的图元（<see cref="lastVertexID"/>匹配）中，
        /// 逐个测试，找到最接近摄像机的那个图元，
        /// 返回此图元的最后一个索引在<see cref="indexBufferPtr"/>中的索引（位置）。
        /// </summary>
        /// <param name="lastIndexIDList"></param>
        /// <returns></returns>
        private RecognizedPrimitiveIndex GetLastIndexID(
            ICamera camera,
            List<RecognizedPrimitiveIndex> lastIndexIDList,
            int x, int y, int canvasWidth, int canvasHeight)
        {
            if (lastIndexIDList.Count == 0) { throw new ArgumentException(); }

            int current = 0;
            for (int i = 1; i < lastIndexIDList.Count; i++)
            {
                OneIndexBufferPtr twoPrimitivesIndexBufferPtr = AssembleIndexBuffer(
                    lastIndexIDList[current], lastIndexIDList[i], this.indexBufferPtr.Mode);
                uint pickedIndex = Pick(camera, twoPrimitivesIndexBufferPtr, x, y, canvasWidth, canvasHeight);
                if (pickedIndex == 1)
                { current++; }
            }

            return lastIndexIDList[current];
        }

        private uint Pick(ICamera camera, OneIndexBufferPtr twoPrimitivesIndexBufferPtr, int x, int y, int canvasWidth, int canvasHeight)
        {
            // 暂存clear color
            var originalClearColor = new float[4];
            GL.GetFloat(GetTarget.ColorClearValue, originalClearColor);

            GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);// 白色意味着没有拾取到任何对象
            GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);

            // 恢复clear color
            GL.ClearColor(originalClearColor[0], originalClearColor[1], originalClearColor[2], originalClearColor[3]);

            //this.positionBufferPtr.Render()
            var arg = new RenderEventArgs(RenderModes.ColorCodedPicking, camera);

            GL.Flush();
            throw new NotImplementedException();
        }

        private OneIndexBufferPtr AssembleIndexBuffer(
            RecognizedPrimitiveIndex recognizedPrimitiveIndex1,
            RecognizedPrimitiveIndex recognizedPrimitiveIndex2,
            DrawMode drawMode)
        {
            List<uint> indexArray = ArrangeIndexes(recognizedPrimitiveIndex1, recognizedPrimitiveIndex1);
            if (indexArray.Count !=
                recognizedPrimitiveIndex1.IndexIDList.Count
                + 1
                + recognizedPrimitiveIndex2.IndexIDList.Count)
            { throw new Exception(); }

            using (var indexBuffer = new OneIndexBuffer<uint>(drawMode, BufferUsage.StaticDraw))
            {
                indexBuffer.Alloc(
                    recognizedPrimitiveIndex1.IndexIDList.Count
                    + 1
                    + recognizedPrimitiveIndex2.IndexIDList.Count);
                unsafe
                {
                    var array = (uint*)indexBuffer.FirstElement();
                    for (int i = 0; i < indexArray.Count; i++)
                    {
                        array[i] = indexArray[i];<commit_msg>Pick(ICamera camera, OneIndexBufferPtr twoPrimitivesIndexBufferPtr, int x, int y, int canvasWidth, int canvasHeight)<commit_after>﻿using GLM;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpGL
{
    //TODO:  copyed from ModernRenderer, need to update(This is complex)
    public partial class OneIndexModernRenderer
    {

        public override IPickedGeometry Pick(ICamera camera, uint stageVertexID,
            int x, int y, int canvasWidth, int canvasHeight)
        {
            uint lastVertexID;
            PickedGeometry pickedGeometry = null;
            if (this.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
            {
                // 找到 lastIndexID
                RecognizedPrimitiveIndex lastIndexID = this.GetLastIndexIDOfPickedGeometry(
                    camera, lastVertexID, x, y, canvasWidth, canvasHeight);
                // 获取pickedGeometry
                pickedGeometry = this.GetGeometry(lastIndexID, stageVertexID);
            }

            return pickedGeometry;
        }

        private PickedGeometry GetGeometry(RecognizedPrimitiveIndex lastIndexID, uint stageVertexID)
        {
            var pickedGeometry = new PickedGeometry();
            pickedGeometry.GeometryType = this.indexBufferPtr.Mode.ToPrimitiveMode().ToGeometryType();
            pickedGeometry.StageVertexID = stageVertexID;
            pickedGeometry.From = this;
            //TODO: 
            //pickedGeometry.Positions = ?
            pickedGeometry.Indexes = lastIndexID.IndexIDList.ToArray();

            return pickedGeometry;
        }

        private RecognizedPrimitiveIndex GetLastIndexIDOfPickedGeometry(
            ICamera camera,
            uint lastVertexID, int x, int y, int canvasWidth, int canvasHeight)
        {
            List<RecognizedPrimitiveIndex> lastIndexIDList = GetLastIndexIDList(lastVertexID);

            RecognizedPrimitiveIndex lastIndexID = GetLastIndexID(
                camera, lastIndexIDList, x, y, canvasWidth, canvasHeight);

            return lastIndexID;
        }

        /// <summary>
        /// 在所有可能的图元（<see cref="lastVertexID"/>匹配）中，
        /// 逐个测试，找到最接近摄像机的那个图元，
        /// 返回此图元的最后一个索引在<see cref="indexBufferPtr"/>中的索引（位置）。
        /// </summary>
        /// <param name="lastIndexIDList"></param>
        /// <returns></returns>
        private RecognizedPrimitiveIndex GetLastIndexID(
            ICamera camera,
            List<RecognizedPrimitiveIndex> lastIndexIDList,
            int x, int y, int canvasWidth, int canvasHeight)
        {
            if (lastIndexIDList.Count == 0) { throw new ArgumentException(); }

            int current = 0;
            for (int i = 1; i < lastIndexIDList.Count; i++)
            {
                OneIndexBufferPtr twoPrimitivesIndexBufferPtr = AssembleIndexBuffer(
                    lastIndexIDList[current], lastIndexIDList[i], this.indexBufferPtr.Mode);
                uint pickedIndex = Pick(camera, twoPrimitivesIndexBufferPtr, x, y, canvasWidth, canvasHeight);
                if (pickedIndex == 1)
                { current++; }
                else if (pickedIndex == 0)
                { /* nothing to do */}
                else
                { throw new Exception("This should not happen!"); }
            }

            return lastIndexIDList[current];
        }

        private uint Pick(ICamera camera, OneIndexBufferPtr twoPrimitivesIndexBufferPtr, int x, int y, int canvasWidth, int canvasHeight)
        {
            Render4Picking(camera, twoPrimitivesIndexBufferPtr);

            uint pickedIndex = ReadPixel(x, y, canvasHeight);

            return pickedIndex;
        }

        private static uint ReadPixel(int x, int y, int canvasHeight)
        {
            // get coded color.
            //byte[] codedColor = new byte[4];
            UnmanagedArray<byte> codedColor = new UnmanagedArray<byte>(4);
            GL.ReadPixels(x, canvasHeight - y - 1, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, codedColor.Header);
            if (!
                // This is when (x, y) is on background and no primitive is picked.
                (codedColor[0] == byte.MaxValue && codedColor[1] == byte.MaxValue
                && codedColor[2] == byte.MaxValue && codedColor[3] == byte.MaxValue))
            {
                // see http://www.cnblogs.com/bitzhuwei/p/modern-opengl-picking-primitive-in-VBO-2.html
                uint shiftedR = (uint)codedColor[0];
                uint shiftedG = (uint)codedColor[1] << 8;
                uint shiftedB = (uint)codedColor[2] << 16;
                uint shiftedA = (uint)codedColor[3] << 24;
                uint stageVertexID = shiftedR + shiftedG + shiftedB + shiftedA;

                return stageVertexID;
            }
            else
            { throw new Exception("This should not happen!"); }
        }

        private void Render4Picking(ICamera camera, OneIndexBufferPtr twoPrimitivesIndexBufferPtr)
        {
            // 暂存clear color
            var originalClearColor = new float[4];
            GL.GetFloat(GetTarget.ColorClearValue, originalClearColor);

            GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);// 白色意味着没有拾取到任何对象
            GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);

            // 恢复clear color
            GL.ClearColor(originalClearColor[0], originalClearColor[1], originalClearColor[2], originalClearColor[3]);

            ShaderProgram program = PickingShaderHelper.GetPickingShaderProgram();
            // 绑定shader
            program.Bind();
            program.SetUniform("pickingBaseID", 0u);
            pickingMVP.SetUniform(program);
            foreach (var item in switchList) { item.On(); }
            {
                var arg = new RenderEventArgs(RenderModes.ColorCodedPicking, camera);
                this.positionBufferPtr.Render(arg, program);
                twoPrimitivesIndexBufferPtr.Render(arg, program);
            }
            foreach (var item in switchList) { item.Off(); }

            pickingMVP.ResetUniform(program);

            // 解绑shader
            program.Unbind();

            GL.Flush();
        }

        private OneIndexBufferPtr AssembleIndexBuffer(
            RecognizedPrimitiveIndex recognizedPrimitiveIndex1,
            RecognizedPrimitiveIndex recognizedPrimitiveIndex2,
            DrawMode drawMode)
        {
            List<uint> indexArray = ArrangeIndexes(recognizedPrimitiveIndex1, recognizedPrimitiveIndex1);
            if (indexArray.Count !=
                recognizedPrimitiveIndex1.IndexIDList.Count
                + 1
                + recognizedPrimitiveIndex2.IndexIDList.Count)
            { throw new Exception(); }

            using (var indexBuffer = new OneIndexBuffer<uint>(drawMode, BufferUsage.StaticDraw))
            {
                indexBuffer.Alloc(
                    recognizedPrimitiveIndex1.IndexIDList.Count
                    + 1
                    + recognizedPrimitiveIndex2.IndexIDList.Count);
                unsafe
                {
                    var array = (uint*)indexBuffer.FirstElement();
                    for (int i = 0; i < indexArray.Count; i++)
                    {
                        array[i] = indexArray[i];
{'fraction_non_alphanumeric': 0.08492688413948256, 'fraction_numerical': 0.006347420858107022, 'mean_word_length': 1.9985545651650205, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1794439', 'n_tokens_mistral': 3396, 'n_tokens_neox': 3305, 'n_words': 689}