IPickedGeometry IColorCodedPicking.Pick(uint stageVertexID)
        {
            IColorCodedPicking    element        = this as IColorCodedPicking;
            PickedGeometryIndexed pickedGeometry = element.TryPick <PickedGeometryIndexed>(
                PrimitiveModes.TriangleStrip, stageVertexID);

            if (pickedGeometry == null)
            {
                return(null);
            }

            // Fill primitive's positions and colors. This maybe changes much more than lines above in second dev.
            uint lastVertexID;

            if (element.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
            {
                pickedGeometry.CubeIndex = lastVertexID / 8;
                var vertexIndex = lastVertexID % 8;
                pickedGeometry.positions = new vec3[1] {
                    unitCubePos[vertexIndex]
                };
            }

            return(pickedGeometry);
        }
Example #2
0
        public override string ToString()
        {
            var positions = this.positions;

            if (positions == null)
            {
                positions = new vec3[0];
            }

            string strPositions = positions.PrintArray();

            uint stageVertexID         = this.StageVertexID;
            IColorCodedPicking picking = this.From;

            string lastVertexID = "?";

            if (picking != null)
            {
                uint tmp;
                if (picking.GetLastVertexIDOfPickedGeometry(stageVertexID, out tmp))
                {
                    lastVertexID = string.Format("{0}", tmp);
                }
            }

            string result = string.Format("{0}: P: {1} vertex ID:{2}/{3} ∈{4}",
                                          GeometryType, strPositions, lastVertexID, stageVertexID, From);

            return(result);
            //return base.ToString();
        }
Example #3
0
        private IPickedGeometry Pick(SceneElement element, uint stageVertexID)
        {
            IPickedGeometry    pickedGeometry = null;
            IColorCodedPicking pickingElement = element as IColorCodedPicking;

            if (pickingElement != null)
            {
                pickedGeometry = pickingElement.Pick(stageVertexID);
            }

            if (pickedGeometry == null)
            {
                if (element != null)
                {
                    foreach (var item in element.Children)
                    {
                        pickedGeometry = Pick(item, stageVertexID);
                        if (pickedGeometry != null)
                        {
                            break;
                        }
                    }
                }
            }

            return(pickedGeometry);
        }
Example #4
0
        /// <summary>
        /// Returns last vertex's id of picked geometry if the geometry represented by <paramref name="stageVertexID"/> belongs to this <paramref name="element"/> instance.
        /// <para>Returns false if <paramref name="stageVertexID"/> the primitive is in some other element.</para>
        /// </summary>
        /// <param name="element"></param>
        /// <param name="stageVertexID"></param>
        /// <param name="lastVertexID"></param>
        /// <returns></returns>
        public static bool GetLastVertexIDOfPickedGeometry(this IColorCodedPicking element, uint stageVertexID, out uint lastVertexID)
        {
            lastVertexID = uint.MaxValue;
            bool result = false;

            if (element != null)
            {
                if (stageVertexID < element.PickingBaseID) // ID is in some previous element.
                {
                    return(false);
                }

                uint vertexCount = element.GetVertexCount();
                uint id          = stageVertexID - element.PickingBaseID;
                if (id < vertexCount)
                {
                    lastVertexID = id;
                    result       = true;
                }
                else // ID is in some subsequent element.
                {
                    result = false;
                }
            }

            return(result);
        }
Example #5
0
        //private void glCanvas1_MouseClick(object sender, MouseEventArgs e)
        //{
        //    if (e.Button == System.Windows.Forms.MouseButtons.Right)
        //    {
        //        IPickedGeometry pickedGeometry = this.Pick(e.X, e.Y);
        //        if (pickedGeometry != null)
        //        {
        //            this.txtPickedInfo.Text = string.Format("{0:yyyy-MM-dd HH:mm:ss.ff} {1}",
        //                DateTime.Now, pickedGeometry);
        //        }
        //        else
        //        {
        //            this.txtPickedInfo.Text = string.Format("{0:yyyy-MM-dd HH:mm:ss.ff} {1}",
        //                DateTime.Now, "nothing picked");
        //        }
        //    }
        //}

        private IPickedGeometry Pick(int x, int y)
        {
            //this.glCanvas1.MakeCurrent();
            // render the scene for color-coded picking.
            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);

            SharedStageInfo info = new SharedStageInfo();

            info.Reset();
            var arg = new RenderEventArgs(RenderModes.HitTest, this.camera);

            IColorCodedPicking pickable = this.element;

            info.RenderForPicking(pickable, arg);

            GL.Flush();

            // get coded color.
            //byte[] codedColor = new byte[4];
            UnmanagedArray <byte> codedColor = new UnmanagedArray <byte>(4);

            GL.ReadPixels(x, this.glCanvas1.Height - y - 1, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, codedColor.Header);
            if (codedColor[0] == byte.MaxValue && codedColor[1] == byte.MaxValue &&
                codedColor[2] == byte.MaxValue && codedColor[3] == byte.MaxValue)
            {
                // This is when (x, y) is on background and no primitive is picked.
                return(null);
            }

            /* // This is how is vertexID coded into color in vertex shader.
             *  int objectID = gl_VertexID;
             *  codedColor = vec4(
             *      float(objectID & 0xFF),
             *      float((objectID >> 8) & 0xFF),
             *      float((objectID >> 16) & 0xFF),
             *      float((objectID >> 24) & 0xFF));
             */

            // get vertexID from coded color.
            // the vertexID is the last vertex that constructs the primitive.
            // 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;

            // get picked primitive.
            IPickedGeometry pickedGeometry = null;

            pickedGeometry = ((IColorCodedPicking)this.element).Pick(stageVertexID);

            return(pickedGeometry);
        }
Example #6
0
        /// <summary>
        /// Get the primitive of <paramref name="element"/> according to vertex's id.
        /// <para>Returns <code>null</code> if <paramref name="element"/> is null or <paramref name="stageVertexID"/> does not belong to any of this <paramref name="element"/>'s vertices.</para>
        /// <para>Note: the <paramref name="stageVertexID"/> refers to the last vertex that constructs the primitive. And it's unique in scene's all elements.</para>
        /// </summary>
        /// <typeparam name="T">Subclass of <see cref="IPickedGeometry"/></typeparam>
        /// <param name="element">the scene's element that contains the primitive.</param>
        /// <param name="mode">specifies what type of primitive it is.</param>
        /// <param name="stageVertexID">Refers to the last vertex that constructs the primitive. And it's unique in scene's all elements.</param>
        /// <param name="positions">element's vertices' position array.</param>
        /// <returns></returns>
        public static T TryPick <T>(
            this IColorCodedPicking element, PrimitiveModes mode, uint stageVertexID, float[] positions)
            where T : IPickedGeometry, new()
        {
            if (positions == null)
            {
                throw new ArgumentNullException("positions");
            }

            T pickedGeometry = element.TryPick <T>(mode, stageVertexID);

            // Fill primitive's positions and colors. This maybe changes much more than lines above in second dev.
            if (pickedGeometry != null)
            {
                uint lastVertexID;
                if (element.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
                {
                    int vertexCount = pickedGeometry.GeometryType.GetVertexCount();
                    if (vertexCount == -1)
                    {
                        vertexCount = positions.Length / 3;
                    }
                    float[] geometryPositions = new float[vertexCount * 3];
                    uint    i = lastVertexID * 3 + 2;
                    for (int j = (geometryPositions.Length - 1); j >= 0; i--, j--)
                    {
                        if (i == uint.MaxValue)// This is when mode is GL_LINE_LOOP.
                        {
                            i = (uint)positions.Length - 1;
                        }
                        geometryPositions[j] = positions[i];
                    }

                    var poss = new vec3[vertexCount];
                    for (int t = 0; t < vertexCount; t++)
                    {
                        poss[t] = new vec3(geometryPositions[t * 3 + 0], geometryPositions[t * 3 + 1], geometryPositions[t * 3 + 2]);
                    }
                    pickedGeometry.positions = poss;
                }
            }

            return(pickedGeometry);
        }
        IPickedGeometry IColorCodedPicking.Pick(uint stageVertexID)
        {
            IColorCodedPicking    element        = this as IColorCodedPicking;
            PickedGeometryColored pickedGeometry = element.TryPick <PickedGeometryColored>(
                this.Model.Mode, stageVertexID, this.Model.Positions);

            if (pickedGeometry == null)
            {
                return(null);
            }

            // Fill primitive's positions and colors. This maybe changes much more than lines above in second dev.
            uint lastVertexID;

            if (element.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
            {
                ScientificModel model = this.Model;

                int vertexCount = pickedGeometry.GeometryType.GetVertexCount();
                if (vertexCount == -1)
                {
                    vertexCount = model.VertexCount;
                }

                float[] geometryColors = new float[vertexCount * 3];

                float[] modelColors = model.Colors;

                uint i = lastVertexID * 3 + 2;
                for (int j = (geometryColors.Length - 1); j >= 0; i--, j--)
                {
                    if (i == uint.MaxValue)// This is when mode is GL_LINE_LOOP.
                    {
                        i = (uint)modelColors.Length - 1;
                    }
                    geometryColors[j] = modelColors[i];
                }

                pickedGeometry.colors = geometryColors;
            }

            return(pickedGeometry);
        }
Example #8
0
        /// <summary>
        /// Get the primitive of <paramref name="element"/> according to vertex's id.
        /// <para>Returns <code>null</code> if <paramref name="element"/> is null or <paramref name="stageVertexID"/> is not in the range of this <paramref name="element"/>.</para>
        /// <para>Note: the <paramref name="stageVertexID"/> Refers to the last vertex that constructs the primitive. And it's unique in scene's all elements.</para>
        /// <para>Note: The result's positions property is not set up as there will be different kinds of storage mode for positions(float[], IntPtr, etc). You have to initialize the positions property and fill correct position information afterwards.</para>
        /// </summary>
        /// <typeparam name="T">Sub type of <see cref="IPickedGeometry"/></typeparam>
        /// <param name="element">the scene's element that contains the primitive.</param>
        /// <param name="mode">specifies what type of primitive it is.</param>
        /// <param name="stageVertexID">Refers to the last vertex that constructs the primitive. And it's unique in scene's all elements.</param>
        /// <returns></returns>
        public static T TryPick <T>(
            this IColorCodedPicking element, PrimitiveModes mode, uint stageVertexID)
            where T : IPickedGeometry, new()
        {
            T pickedGeometry = default(T);

            if (element != null)
            {
                uint lastVertexID;
                if (element.GetLastVertexIDOfPickedGeometry(stageVertexID, out lastVertexID))
                {
                    pickedGeometry = new T();

                    pickedGeometry.GeometryType  = mode.ToGeometryType();
                    pickedGeometry.StageVertexID = stageVertexID;
                    pickedGeometry.From          = element;
                }
            }

            return(pickedGeometry);
        }
Example #9
0
        /// <summary>
        /// Render the element that inherts <see cref="IColorCodedPicking"/> for color coded picking.
        /// </summary>
        /// <param name="pickable"></param>
        /// <param name="gl"></param>
        /// <param name="renderMode"></param>
        public virtual void RenderForPicking(IColorCodedPicking pickable, RenderEventArgs e)
        {
            if (pickable != null)
            {
                pickable.PickingBaseID = this.RenderedVertexCount;

                //  render the element.
                pickable.Render(e);

                uint rendered = this.RenderedVertexCount + pickable.GetVertexCount();
                if (this.RenderedVertexCount <= rendered)
                {
                    this.RenderedVertexCount = rendered;
                }
                else
                {
                    throw new OverflowException(
                              string.Format("Too many geometries({0} + {1} > {2}) for color coded picking.",
                                            this.RenderedVertexCount, pickable.GetVertexCount(), uint.MaxValue));
                }
            }
        }
Example #10
0
        /// <summary>
        /// Render the element that inherts <see cref="IColorCodedPicking"/> for color coded picking.
        /// </summary>
        /// <param name="pickable"></param>
        /// <param name="gl"></param>
        /// <param name="renderMode"></param>
        public virtual void RenderForPicking(IColorCodedPicking pickable, RenderEventArgs e)
        {
            if (pickable != null)
            {
                pickable.PickingBaseID = this.RenderedVertexCount;

                //  render the element.
                IRenderable renderable = pickable;
                renderable.Render(e);

                uint rendered = this.RenderedVertexCount + pickable.GetVertexCount();
                if (this.RenderedVertexCount <= rendered)
                {
                    this.RenderedVertexCount = rendered;
                }
                else
                {
                    throw new OverflowException(
                        string.Format("Too many geometries({0} + {1} > {2}) for color coded picking.",
                            this.RenderedVertexCount, pickable.GetVertexCount(), uint.MaxValue));
                }
            }
        }
Example #11
0
        private void glCanvas1_MouseMove(object sender, MouseEventArgs e)
        {
            if (rotator.MouseDownFlag)
            {
                rotator.MouseMove(e.X, e.Y);
                this.cameraUpdated = true;
            }

            {
                IColorCodedPicking pickable = this.renderer;
                pickable.MVP = this.camera.GetProjectionMat4() * this.camera.GetViewMat4();
                IPickedGeometry pickedGeometry = ColorCodedPicking.Pick(
                    this.camera, e.X, e.Y, this.glCanvas1.Width, this.glCanvas1.Height, pickable);
                if (pickedGeometry != null)
                {
                    this.bulletinBoard.SetContent(pickedGeometry.ToString());
                }
                else
                {
                    this.bulletinBoard.SetContent("picked nothing.");
                }
            }
        }
        /// <summary>
        /// Render the element that inherts <see cref="IColorCodedPicking"/> for color coded picking.
        /// </summary>
        /// <param name="picking"></param>
        /// <param name="gl"></param>
        /// <param name="renderMode"></param>
        public virtual void RenderForPicking(IColorCodedPicking picking, OpenGL gl, SceneGraph.Core.RenderMode renderMode)
        {
            if (picking != null)
            {
                picking.PickingBaseID = this.RenderedVertexCount;

                //  render the element.
                SharpGL.SceneGraph.Core.IRenderable renderable = picking;
                renderable.Render(gl, renderMode);

                uint rendered = this.RenderedVertexCount + picking.GetVertexCount();
                if (this.RenderedVertexCount <= rendered)
                {
                    this.RenderedVertexCount = rendered;
                }
                else
                {
                    throw new OverflowException(
                              string.Format("Too many geometries({0} + {1} > {2}) for color coded picking.",
                                            this.RenderedVertexCount, picking.GetVertexCount(), uint.MaxValue));
                }
            }
        }
Example #13
0
        //public override void Draw(SceneGraph.Cameras.Camera camera = null)
        //{
        //    this.Draw(camera, RenderMode.Design);
        //}

        /// <summary>
        /// Renders the element.
        /// </summary>
        /// <param name="gl">The gl.</param>
        /// <param name="renderMode">The render mode.</param>
        public void MyRenderElement(SceneElement sceneElement, OpenGL gl, RenderMode renderMode, SharedStageInfo info)
        {
            //  If the element is disabled, we're done.
            if (sceneElement.IsEnabled == false)
            {
                return;
            }

            //  Push each effect.
            foreach (var effect in sceneElement.Effects)
            {
                if (effect.IsEnabled)
                {
                    effect.Push(gl, sceneElement);
                }
            }

            //  If the element can be bound, bind it.
            IBindable bindable = sceneElement as IBindable;// example: Light

            if (bindable != null)
            {
                bindable.Push(gl);
            }

            //  If the element has an object space, transform into it.
            IHasObjectSpace hasObjectSpace = sceneElement as IHasObjectSpace;// example: Polygon, quadric, Teapot

            if (hasObjectSpace != null)
            {
                hasObjectSpace.PushObjectSpace(gl);
            }

            //  Render self.
            {
                //  If the element has a material, push it.
                IHasMaterial hasMaterial = sceneElement as IHasMaterial;// example: Polygon, quadric, Teapot
                if (hasMaterial != null && hasMaterial.Material != null)
                {
                    hasMaterial.Material.Push(gl);
                }

                if (renderMode == RenderMode.HitTest)
                {
                    IColorCodedPicking picking = sceneElement as IColorCodedPicking;
                    info.RenderForPicking(picking, gl, renderMode);
                }
                else
                {
                    //  If the element can be rendered, render it.
                    IRenderable renderable = sceneElement as IRenderable;
                    if (renderable != null)
                    {
                        renderable.Render(gl, renderMode);
                    }
                }

                //  If the element has a material, pop it.
                if (hasMaterial != null && hasMaterial.Material != null)
                {
                    hasMaterial.Material.Pop(gl);
                }
            }

            //  If the element is volume bound and we are rendering volumes, render the volume.
            IVolumeBound volumeBound = null;

            if (RenderBoundingVolumes)
            {
                volumeBound = sceneElement as IVolumeBound;
                if (volumeBound != null)
                {
                    volumeBound.BoundingVolume.Render(gl, renderMode);
                }
            }

            //  Recurse through the children.
            foreach (var childElement in sceneElement.Children)
            {
                MyRenderElement(childElement, gl, renderMode, info);
            }

            //  If the element has an object space, transform out of it.
            if (hasObjectSpace != null)
            {
                hasObjectSpace.PopObjectSpace(gl);
            }

            //  If the element can be bound, bind it.
            if (bindable != null)
            {
                bindable.Pop(gl);
            }

            //  Pop each effect.
            for (int i = sceneElement.Effects.Count - 1; i >= 0; i--)
            {
                if (sceneElement.Effects[i].IsEnabled)
                {
                    sceneElement.Effects[i].Pop(gl, sceneElement);
                }
            }
        }
Example #14
0
        /// <summary>
        /// Get geometry's count according to specified <paramref name="mode"/>.
        /// <para>Returns false if the <paramref name="element"/> is null.</para>
        /// </summary>
        /// <param name="element"></param>
        /// <param name="mode"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static bool GetGeometryCount(this IColorCodedPicking element, PrimitiveModes mode, out uint count)
        {
            bool result = false;

            count = uint.MaxValue;

            if (element != null)
            {
                uint vertexCount = element.GetVertexCount();

                switch (mode)
                {
                case PrimitiveModes.Points:
                    count = vertexCount;
                    break;

                case PrimitiveModes.Lines:
                    count = vertexCount / 2;
                    break;

                case PrimitiveModes.LineLoop:
                    count = vertexCount;
                    break;

                case PrimitiveModes.LineStrip:
                    count = vertexCount - 1;
                    break;

                case PrimitiveModes.Triangles:
                    count = vertexCount / 3;
                    break;

                case PrimitiveModes.TriangleStrip:
                    count = vertexCount - 2;
                    break;

                case PrimitiveModes.TriangleFan:
                    count = vertexCount - 2;
                    break;

                case PrimitiveModes.Quads:
                    count = vertexCount / 4;
                    break;

                case PrimitiveModes.QuadStrip:
                    count = vertexCount / 2 - 1;
                    break;

                case PrimitiveModes.Polygon:
                    count = 1;
                    break;

                default:
                    throw new NotImplementedException();
                }

                result = true;
            }

            return(result);
        }
Example #15
0
        /// <summary>
        /// Get geometry's index(start from 0) according to <paramref name="lastVertexID"/> and <paramref name="mode"/>.
        /// <para>Returns false if failed.</para>
        /// </summary>
        /// <param name="element"></param>
        /// <param name="mode"></param>
        /// <param name="lastVertexID">Refers to the last vertex that constructs the primitive.
        /// <para>Ranges from 0 to (<paramref name="element"/>'s vertices' count - 1).</para></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static bool GetGeometryIndex(this IColorCodedPicking element, PrimitiveModes mode, uint lastVertexID, out uint index)
        {
            index = uint.MaxValue;
            if (element == null)
            {
                return(false);
            }

            uint vertexCount = element.GetVertexCount();

            if (lastVertexID < vertexCount)
            {
                switch (mode)
                {
                case PrimitiveModes.Points:
                    // vertexID should range from 0 to vertexCount - 1.
                    index = lastVertexID;
                    break;

                case PrimitiveModes.Lines:
                    // vertexID should range from 0 to vertexCount - 1.
                    index = lastVertexID / 2;
                    break;

                case PrimitiveModes.LineLoop:
                    // vertexID should range from 0 to vertexCount.
                    if (lastVertexID == 0)     // This is the last primitive.
                    {
                        index = vertexCount - 1;
                    }
                    else
                    {
                        index = lastVertexID - 1;
                    }
                    break;

                case PrimitiveModes.LineStrip:
                    index = lastVertexID - 1;    // If lastVertexID is 0, this returns -1.
                    break;

                case PrimitiveModes.Triangles:
                    index = lastVertexID / 3;
                    break;

                case PrimitiveModes.TriangleStrip:
                    index = lastVertexID - 2;    // if lastVertexID is 0 or 1, this returns -2 or -1.
                    break;

                case PrimitiveModes.TriangleFan:
                    index = lastVertexID - 2;    // if lastVertexID is 0 or 1, this returns -2 or -1.
                    break;

                case PrimitiveModes.Quads:
                    index = lastVertexID / 4;
                    break;

                case PrimitiveModes.QuadStrip:
                    index = lastVertexID / 2 - 1;    // If lastVertexID is 0 or 1, this returns -1.
                    break;

                case PrimitiveModes.Polygon:
                    index = 0;
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            return(true);
        }