예제 #1
0
        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------

        //------------------------------------------------------
        //
        //  Public Events
        //
        //------------------------------------------------------

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        // NOTE: Geometry3D hit testing takes the rayParams in the outer space of the
        //       Geometry3D.  That is, RayHitTest() will apply this geometry's
        //       transform to the ray for the caller.
        //
        //       This is different than Visual hit testing which does not transform
        //       the hit testing parameters by the Visual's transform.
        internal void RayHitTest(RayHitTestParameters rayParams, FaceType facesToHit)
        {
            Debug.Assert(facesToHit != FaceType.None,
                         "Caller should make sure we're trying to hit something");

            Rect3D bounds = Bounds;

            if (bounds.IsEmpty)
            {
                return;
            }

            //



            Point3D  origin;
            Vector3D direction;

            rayParams.GetLocalLine(out origin, out direction);

            if (LineUtil.ComputeLineBoxIntersection(ref origin, ref direction, ref bounds, rayParams.IsRay))
            {
                RayHitTestCore(rayParams, facesToHit);
            }

            //
        }
예제 #2
0
        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------

        //------------------------------------------------------
        //
        //  Public Events
        //
        //------------------------------------------------------

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        // NOTE: Geometry3D hit testing takes the rayParams in the outer space of the
        //       Geometry3D.  That is, RayHitTest() will apply this geometry's
        //       transform to the ray for the caller.
        //
        //       This is different than Visual hit testing which does not transform
        //       the hit testing parameters by the Visual's transform.
        internal void RayHitTest(RayHitTestParameters rayParams, FaceType facesToHit)
        {
            Debug.Assert(facesToHit != FaceType.None,
                         "Caller should make sure we're trying to hit something");

            Rect3D bounds = Bounds;

            if (bounds.IsEmpty)
            {
                return;
            }

            // Geometry3D's do not yet support a Transform property
            //
            // Transform3D transform = Transform;
            // rayParams.PushTransform(transform);


            Point3D  origin;
            Vector3D direction;

            rayParams.GetLocalLine(out origin, out direction);

            if (LineUtil.ComputeLineBoxIntersection(ref origin, ref direction, ref bounds, rayParams.IsRay))
            {
                RayHitTestCore(rayParams, facesToHit);
            }

            // Geometry3D's do not yet support a Transform property
            //
            // rayParams.PopTransform(transform);
        }
        //
        // Hits the ray against the mesh
        //
        internal override void RayHitTestCore(
            RayHitTestParameters rayParams,
            FaceType hitTestableFaces)
        {
            Debug.Assert(hitTestableFaces != FaceType.None, 
                "Caller should make sure we're trying to hit something");

            Point3DCollection positions = Positions;
            if (positions == null)
            {
                return;
            }

            Point3D origin;
            Vector3D direction;

            rayParams.GetLocalLine(out origin, out direction);

            Int32Collection indices = TriangleIndices;

            // In the line case, we want to hit test all faces because we don't
            // have a direction. This may differ from what faces we want to
            // accept.
            FaceType facesToHit;
            if (rayParams.IsRay)
            {
                facesToHit = hitTestableFaces;
            }
            else
            {
                facesToHit = FaceType.Front | FaceType.Back;
            }

            
            //
            // This code duplication is unfortunate but necessary. Breaking it down into methods 
            // further significantly impacts performance. About 5% improvement could be made
            // by unrolling this code below even more.
            //
            // If futher perf investigation is done with this code, be sure to test NGEN assemblies only
            // as JIT produces different, faster code than NGEN.
            //
            
            if (indices == null || indices.Count == 0)
            {
                FrugalStructList<Point3D> ps = positions._collection; 
                int count = ps.Count - (ps.Count % 3);
                
                for (int i = count - 1; i >= 2; i -= 3)
                {
                    int i0 = i - 2;
                    int i1 = i - 1;
                    int i2 = i;
                    
                    Point3D v0 = ps[i0];
                    Point3D v1 = ps[i1];
                    Point3D v2 = ps[i2];
                
                    double hitTime;
                    Point barycentric;

                    // The line hit test is equivalent to a double sided
                    // triangle hit because it doesn't cull triangles based
                    // on winding
                    if (LineUtil.ComputeLineTriangleIntersection(
                            facesToHit,
                            ref origin,
                            ref direction,
                            ref v0,
                            ref v1,
                            ref v2,
                            out barycentric,
                            out hitTime
                            )
                        )
                    {        
                        
                        if (rayParams.IsRay)
                        {                          
                            ValidateRayHit(
                                rayParams, 
                                ref origin, 
                                ref direction, 
                                hitTime,
                                i0,
                                i1,
                                i2,
                                ref barycentric
                                );
                        }
                        else
                        {
                            ValidateLineHit(
                                rayParams, 
                                hitTestableFaces, 
                                i0,
                                i1,
                                i2,
                                ref v0,
                                ref v1,
                                ref v2,
                                ref barycentric
                                );
                        }
                    }
                }

            }
            else // indexed mesh
            {
                FrugalStructList<Point3D> ps = positions._collection;
                FrugalStructList<int> idcs = indices._collection;
                
                int count = idcs.Count;
                int limit = ps.Count;
                                          
                for (int i = 2; i < count; i += 3)
                {
                    int i0 = idcs[i - 2];
                    int i1 = idcs[i - 1];
                    int i2 = idcs[i];
                
                    // Quit if we encounter an index out of range.
                    // This is okay because the triangles we ignore are not rendered.
                    //  (see: CMilMeshGeometry3DDuce::Realize)
                    if ((0 > i0 || i0 >= limit) ||
                        (0 > i1 || i1 >= limit) ||
                        (0 > i2 || i2 >= limit))
                    {
                        break;
                    }
                
                    Point3D v0 = ps[i0];
                    Point3D v1 = ps[i1];
                    Point3D v2 = ps[i2];
                
                    double hitTime;
                    Point barycentric;
                    
                    if (LineUtil.ComputeLineTriangleIntersection(
                            facesToHit,
                            ref origin,
                            ref direction,
                            ref v0,
                            ref v1,
                            ref v2,
                            out barycentric,
                            out hitTime
                            )
                        )
                    {        
                        if (rayParams.IsRay)
                        {   
                            ValidateRayHit(
                                rayParams, 
                                ref origin, 
                                ref direction, 
                                hitTime,
                                i0,
                                i1,
                                i2,
                                ref barycentric
                                );
                        }
                        else
                        {
                            ValidateLineHit(
                                rayParams, 
                                hitTestableFaces, 
                                i0,
                                i1,
                                i2,
                                ref v0,
                                ref v1,
                                ref v2,
                                ref barycentric
                                );
                        }
                    }
                }
            }
        }
예제 #4
0
파일: Visual3D.cs 프로젝트: JianwenSun/cc
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
        
        #region Internal Methods

        internal bool DoesRayHitSubgraphBounds(RayHitTestParameters rayParams)
        {
            Point3D origin;
            Vector3D direction;
            rayParams.GetLocalLine(out origin, out direction);

            Rect3D bboxSubgraph = VisualDescendantBounds;
            return LineUtil.ComputeLineBoxIntersection(ref origin, ref direction, ref bboxSubgraph, rayParams.IsRay);
        }
예제 #5
0
파일: Geometry3D.cs 프로젝트: JianwenSun/cc
        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------
        
        //------------------------------------------------------
        //
        //  Public Events
        //
        //------------------------------------------------------
       
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        // NOTE: Geometry3D hit testing takes the rayParams in the outer space of the
        //       Geometry3D.  That is, RayHitTest() will apply this geometry's 
        //       transform to the ray for the caller.
        //
        //       This is different than Visual hit testing which does not transform
        //       the hit testing parameters by the Visual's transform.
        internal void RayHitTest(RayHitTestParameters rayParams, FaceType facesToHit)
        {
            Debug.Assert(facesToHit != FaceType.None, 
                "Caller should make sure we're trying to hit something");
               
            Rect3D bounds = Bounds;

            if (bounds.IsEmpty)
            {
                return;
            }

            // 




            Point3D origin;
            Vector3D direction;

            rayParams.GetLocalLine(out origin, out direction);

            if (LineUtil.ComputeLineBoxIntersection(ref origin, ref direction, ref bounds, rayParams.IsRay))
            {
                RayHitTestCore(rayParams, facesToHit);
            }
            
            // 


        }
예제 #6
0
        //
        // Hits the ray against the mesh
        //
        internal override void RayHitTestCore(
            RayHitTestParameters rayParams,
            FaceType hitTestableFaces)
        {
            Debug.Assert(hitTestableFaces != FaceType.None,
                         "Caller should make sure we're trying to hit something");

            Point3DCollection positions = Positions;

            if (positions == null)
            {
                return;
            }

            Point3D  origin;
            Vector3D direction;

            rayParams.GetLocalLine(out origin, out direction);

            Int32Collection indices = TriangleIndices;

            // In the line case, we want to hit test all faces because we don't
            // have a direction. This may differ from what faces we want to
            // accept.
            FaceType facesToHit;

            if (rayParams.IsRay)
            {
                facesToHit = hitTestableFaces;
            }
            else
            {
                facesToHit = FaceType.Front | FaceType.Back;
            }


            //
            // This code duplication is unfortunate but necessary. Breaking it down into methods
            // further significantly impacts performance. About 5% improvement could be made
            // by unrolling this code below even more.
            //
            // If futher perf investigation is done with this code, be sure to test NGEN assemblies only
            // as JIT produces different, faster code than NGEN.
            //

            if (indices == null || indices.Count == 0)
            {
                FrugalStructList <Point3D> ps = positions._collection;
                int count = ps.Count - (ps.Count % 3);

                for (int i = count - 1; i >= 2; i -= 3)
                {
                    int i0 = i - 2;
                    int i1 = i - 1;
                    int i2 = i;

                    Point3D v0 = ps[i0];
                    Point3D v1 = ps[i1];
                    Point3D v2 = ps[i2];

                    double hitTime;
                    Point  barycentric;

                    // The line hit test is equivalent to a double sided
                    // triangle hit because it doesn't cull triangles based
                    // on winding
                    if (LineUtil.ComputeLineTriangleIntersection(
                            facesToHit,
                            ref origin,
                            ref direction,
                            ref v0,
                            ref v1,
                            ref v2,
                            out barycentric,
                            out hitTime
                            )
                        )
                    {
                        if (rayParams.IsRay)
                        {
                            ValidateRayHit(
                                rayParams,
                                ref origin,
                                ref direction,
                                hitTime,
                                i0,
                                i1,
                                i2,
                                ref barycentric
                                );
                        }
                        else
                        {
                            ValidateLineHit(
                                rayParams,
                                hitTestableFaces,
                                i0,
                                i1,
                                i2,
                                ref v0,
                                ref v1,
                                ref v2,
                                ref barycentric
                                );
                        }
                    }
                }
            }
            else // indexed mesh
            {
                FrugalStructList <Point3D> ps   = positions._collection;
                FrugalStructList <int>     idcs = indices._collection;

                int count = idcs.Count;
                int limit = ps.Count;

                for (int i = 2; i < count; i += 3)
                {
                    int i0 = idcs[i - 2];
                    int i1 = idcs[i - 1];
                    int i2 = idcs[i];

                    // Quit if we encounter an index out of range.
                    // This is okay because the triangles we ignore are not rendered.
                    //  (see: CMilMeshGeometry3DDuce::Realize)
                    if ((0 > i0 || i0 >= limit) ||
                        (0 > i1 || i1 >= limit) ||
                        (0 > i2 || i2 >= limit))
                    {
                        break;
                    }

                    Point3D v0 = ps[i0];
                    Point3D v1 = ps[i1];
                    Point3D v2 = ps[i2];

                    double hitTime;
                    Point  barycentric;

                    if (LineUtil.ComputeLineTriangleIntersection(
                            facesToHit,
                            ref origin,
                            ref direction,
                            ref v0,
                            ref v1,
                            ref v2,
                            out barycentric,
                            out hitTime
                            )
                        )
                    {
                        if (rayParams.IsRay)
                        {
                            ValidateRayHit(
                                rayParams,
                                ref origin,
                                ref direction,
                                hitTime,
                                i0,
                                i1,
                                i2,
                                ref barycentric
                                );
                        }
                        else
                        {
                            ValidateLineHit(
                                rayParams,
                                hitTestableFaces,
                                i0,
                                i1,
                                i2,
                                ref v0,
                                ref v1,
                                ref v2,
                                ref barycentric
                                );
                        }
                    }
                }
            }
        }