Ejemplo n.º 1
0
        public Vector3 Reflect(Vector3 normal)
        {
            // reflect incident vector off plane orthogonal to normal
            // normal is assumed to have unit length
            var v1 = new Vector3();

            return(this.Sub(v1.Copy(normal).MultiplyScalar(2 * this.Dot(normal))));
        }
Ejemplo n.º 2
0
        public Vector3 ProjectOnPlane(Vector3 planeNormal)
        {
            var v1 = new Vector3();

            v1.Copy(this).ProjectOnVector(planeNormal);

            return(this.Sub(v1));
        }
Ejemplo n.º 3
0
        public double DistanceToPoint(Vector3 point)
        {
            var v1 = new Vector3();

            var clampedPoint = v1.Copy(point).Clamp(this.min, this.max);

            return(clampedPoint.Sub(point).Length());
        }
Ejemplo n.º 4
0
        public Box3 SetFromCenterAndSize(Vector3 center, Vector3 size)
        {
            var v1 = new Vector3();

            var halfSize = v1.Copy(size).MultiplyScalar(0.5);

            this.min.Copy(center).Sub(halfSize);
            this.max.Copy(center).Add(halfSize);

            return(this);
        }
Ejemplo n.º 5
0
        public double DistanceSqToPoint(Vector3 point)
        {
            var v1 = new Vector3();

            var directionDistance = v1.SubVectors(point, this.origin).Dot(this.direction);

            // point behind the ray

            if (directionDistance < 0)
            {
                return(this.origin.DistanceToSquared(point));
            }

            v1.Copy(this.direction).MultiplyScalar(directionDistance).Add(this.origin);

            return(v1.DistanceToSquared(point));
        }
Ejemplo n.º 6
0
        public double DistanceSqToSegment(Vector3 v0, Vector3 v1, Vector3 optionalPointOnRay = null, Vector3 optionalPointOnSegment = null)
        {
            var segCenter = new Vector3();
            var segDir    = new Vector3();
            var diff      = new Vector3();

            // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
            // It returns the min distance between the ray and the segment
            // defined by v0 and v1
            // It can also set two optional targets :
            // - The closest point on the ray
            // - The closest point on the segment

            segCenter.Copy(v0).Add(v1).MultiplyScalar(0.5);
            segDir.Copy(v1).Sub(v0).Normalize();
            diff.Copy(this.origin).Sub(segCenter);

            var    segExtent = v0.DistanceTo(v1) * 0.5;
            var    a01 = -this.direction.Dot(segDir);
            var    b0 = diff.Dot(this.direction);
            var    b1 = -diff.Dot(segDir);
            var    c = diff.LengthSq();
            var    det = _Math.Abs(1 - a01 * a01);
            double s0, s1, sqrDist, extDet;

            if (det > 0)
            {
                // The ray and segment are not parallel.

                s0     = a01 * b1 - b0;
                s1     = a01 * b0 - b1;
                extDet = segExtent * det;

                if (s0 >= 0)
                {
                    if (s1 >= -extDet)
                    {
                        if (s1 <= extDet)
                        {
                            // region 0
                            // Minimum at interior points of ray and segment.

                            var invDet = 1 / det;
                            s0     *= invDet;
                            s1     *= invDet;
                            sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c;
                        }
                        else
                        {
                            // region 1

                            s1      = segExtent;
                            s0      = _Math.Max(0, -(a01 * s1 + b0));
                            sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
                        }
                    }
                    else
                    {
                        // region 5

                        s1      = -segExtent;
                        s0      = _Math.Max(0, -(a01 * s1 + b0));
                        sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
                    }
                }
                else
                {
                    if (s1 <= -extDet)
                    {
                        // region 4

                        s0      = _Math.Max(0, -(-a01 * segExtent + b0));
                        s1      = (s0 > 0) ? -segExtent : _Math.Min(_Math.Max(-segExtent, -b1), segExtent);
                        sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
                    }
                    else if (s1 <= extDet)
                    {
                        // region 3

                        s0      = 0;
                        s1      = _Math.Min(_Math.Max(-segExtent, -b1), segExtent);
                        sqrDist = s1 * (s1 + 2 * b1) + c;
                    }
                    else
                    {
                        // region 2

                        s0      = _Math.Max(0, -(a01 * segExtent + b0));
                        s1      = (s0 > 0) ? segExtent : _Math.Min(_Math.Max(-segExtent, -b1), segExtent);
                        sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
                    }
                }
            }
            else
            {
                // Ray and segment are parallel.

                s1      = (a01 > 0) ? -segExtent : segExtent;
                s0      = _Math.Max(0, -(a01 * s1 + b0));
                sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            }

            if (optionalPointOnRay != null)
            {
                optionalPointOnRay.Copy(this.direction).MultiplyScalar(s0).Add(this.origin);
            }

            if (optionalPointOnSegment != null)
            {
                optionalPointOnSegment.Copy(segDir).MultiplyScalar(s1).Add(segCenter);
            }

            return(sqrDist);
        }