private void DrawLines_Plate(int numSamples, double half, double lineThickness, AxisFor axisX, AxisFor axisY, AxisFor axisZ)
        {
            const double ELAPSEDURATIONSECONDS = 1;

            // Figure out how wide to make the plate
            int totalSamples = numSamples * numSamples * numSamples;        // numsamples is per axis, so cube it
            int cellsPerSlice = _field.Size * _field.Size;
            int numSlices = Convert.ToInt32(Math.Round(Convert.ToDouble(totalSamples) / Convert.ToDouble(cellsPerSlice)));
            if (numSlices == 0)
            {
                numSlices = 1;
            }

            int toOffset = numSlices / 2;
            int fromOffset = numSlices - toOffset - 1;

            DateTime now = DateTime.UtcNow;

            bool isOverField = false;

            if (_mousePoint != null)
            {
                #region Snap to mouse

                // Cast a ray (Copied this from ItemSelectDragLogic.ChangeDragPlane, DragItem)

                Point3D point = new Point3D(0, 0, 0);

                RayHitTestParameters cameraLookCenter = UtilityWPF.RayFromViewportPoint(_camera, _viewport, new Point(_viewport.ActualWidth * .5d, _viewport.ActualHeight * .5d));

                // Come up with a snap plane
                Vector3D standard = Math3D.GetArbitraryOrhonganal(cameraLookCenter.Direction);
                Vector3D orth = Vector3D.CrossProduct(standard, cameraLookCenter.Direction);
                ITriangle plane = new Triangle(point, point + standard, point + orth);

                DragHitShape dragPlane = new DragHitShape();
                dragPlane.SetShape_Plane(plane);

                // Cast a ray onto that plane from the current mouse position
                RayHitTestParameters mouseRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, _mousePoint.Value);
                Point3D? hitPoint = dragPlane.CastRay(mouseRay);

                if (hitPoint != null)
                {
                    // Find the nearest Z cell
                    double halfSize = (_field.Size * _sizeMult) / 2d;
                    double cellSize = (_field.Size * _sizeMult) / _field.Size;

                    int zIndex = Convert.ToInt32((halfSize - axisZ.GetValue(hitPoint.Value)) / cellSize);

                    if (zIndex >= 0 && zIndex < _field.Size)
                    {
                        isOverField = true;

                        // Cap to field
                        _plateCurrentIndex = _field.Size - zIndex;        // it's actually the opposite
                        if (_plateCurrentIndex - fromOffset < 0)
                        {
                            _plateCurrentIndex = fromOffset;
                        }
                        else if (_plateCurrentIndex + toOffset > _field.Size - 1)
                        {
                            _plateCurrentIndex = _field.Size - toOffset - 1;
                        }

                        _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                    }
                }

                #endregion
            }

            if (!isOverField)
            {
                #region Shift the plate

                if (_plateCurrentIndex + toOffset > _field.Size - 1)
                {
                    _plateCurrentIndex = _field.Size - toOffset - 1;
                    _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                }
                else if (now > _sceneRemaining)
                {
                    _plateCurrentIndex--;

                    if (_plateCurrentIndex - fromOffset <= 0)
                    {
                        _plateCurrentIndex = _field.Size - toOffset - 1;
                    }

                    _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                }

                #endregion
            }

            double[] velX = _field.VelocityX;
            double[] velY = _field.VelocityY;
            double[] velZ = _field.VelocityZ;

            bool[] blocked = _field.Blocked;

            _velocityLines.BeginAddingLines();

            for (int z = _plateCurrentIndex - fromOffset; z <= _plateCurrentIndex + toOffset; z++)
            {
                for (int x = 0; x < _field.Size; x++)
                {
                    for (int y = 0; y < _field.Size; y++)
                    {
                        int xRef = -1;
                        int yRef = -1;
                        int zRef = -1;

                        axisX.Set3DIndex(ref xRef, ref yRef, ref zRef, x);
                        axisY.Set3DIndex(ref xRef, ref yRef, ref zRef, y);
                        axisZ.Set3DIndex(ref xRef, ref yRef, ref zRef, z);

                        int index1D = _field.Get1DIndex(xRef, yRef, zRef);

                        if (blocked[index1D])
                        {
                            continue;
                        }

                        DrawLinesSprtAddLine(xRef, yRef, zRef, index1D, half, lineThickness, velX, velY, velZ);
                    }
                }
            }

            _velocityLines.EndAddingLines();
        }
예제 #2
0
        //TODO: This functionality should be part of MapObjectChaseVelocity
        private static Point3D? AdjustIfOffPlane(Point3D itemPos, double itemRadius, DragHitShape dragPlane, Point3D? chasePoint)
        {
            const double MAXOFFSET = 1.5;
            const double PERCENTATMAX = .01;        // even if they are really far off the plane, don't completely chase the plane, some percent needs to go toward the chase point passed in

            Point3D? pointOnPlane = dragPlane.CastRay(itemPos);
            if (pointOnPlane == null)
            {
                // Don't know where they are relative to the plane (this should never happen)
                return chasePoint;
            }
            else if (Math3D.IsNearValue(pointOnPlane.Value, itemPos))
            {
                // They're position is the same as the point on the plane (they are already on the plane)
                return chasePoint;
            }

            Vector3D vectToPlane = (itemPos - pointOnPlane.Value);
            double distToPlane = vectToPlane.Length;
            if (distToPlane < itemRadius * .01)
            {
                // They are less than a percent of their body size off the plane, just return the point passed in
                return chasePoint;
            }

            if (chasePoint == null)
            {
                // Null was passed in, just go straight for the plane (this should never happen)
                return pointOnPlane;
            }

            // Figure out how much to dive for the plane vs go for the chase point
            double offset = distToPlane / itemRadius;
            double percent = PERCENTATMAX;
            if (offset < MAXOFFSET)
            {
                // They are less than the max allowable distance from the plane
                percent = UtilityCore.GetScaledValue_Capped(PERCENTATMAX, 1d, 0, MAXOFFSET, MAXOFFSET - offset);
            }

            Vector3D direction = chasePoint.Value - pointOnPlane.Value;

            return pointOnPlane.Value + (direction * percent);
        }