public override void StartDrag(RayHitTestParameters ray) { if (_sphereCenter == null || _sphereOrientation == null) { throw new InvalidOperationException("SphereCenter and SphereOrientation need to be set before calling this method"); } if (_dragHitShape == null) { _dragHitShape = new DragHitShape(); } _dragHitShape.SetShape_Sphere(this.SphereCenter, this.Radius); _dragMouseDownClickRay = ray; _dragMouseDownCenterRay = ray; //_dragMouseDownCenterRay = new RayHitTestParameters(this.DragAxis.Origin, ray.Direction); //TODO: the ray through the center of the part really isn't parallel to the click ray (since the perspective camera sees in a cone) // Remember where they clicked (to be able to calculate the rotation in DragItem) Point3D?hitPoint = _dragHitShape.CastRay(ray); if (hitPoint == null) { // This will never happen for sphere _mouseDownHitPoint = new Point3D(0, 0, 0); } else { _mouseDownHitPoint = hitPoint.Value; } _mouseDownOrientation = this.SphereOrientation.ToUnit(); }
public override void DragItem(RayHitTestParameters ray) { if (this.DragAxis == null) { throw new InvalidOperationException("DragAxis needs to be set before calling this method"); } // Compare the ray with the drag axis to see where on the axis they clicked // If the method comes back false, then the click ray is parallel to the axis, so just don't drag the arrow Point3D?hitPoint = _dragHitShape.CastRay(_dragMouseDownClickRay, _dragMouseDownCenterRay, ray); if (hitPoint != null) { this.DragAxis = new RayHitTestParameters(hitPoint.Value, this.DragAxis.Direction); } }
//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)); }
public Point3D?ProjectTo3D() { //TODO: Cache this Vector3D orth = Vector3D.CrossProduct(Look, Up); //TODO: Cache Up as a unit vector // Project the X part of the 2D along orth Vector3D x = orth.ToUnit(true) * (CurrentPoint2D.X / Scale); // Project the Y part along up Vector3D y = Up.ToUnit(true) * (CurrentPoint2D.Y / Scale); if (Math3D.IsInvalid(x) || Math3D.IsInvalid(y)) { return(null); } // Fire a ray along look toward the drag plane return(_dragPlane.CastRay(new RayHitTestParameters(Position + x + y, Look))); }
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(); }
private void DragItem(Point clickPoint) { bool usingAdaptive = this.UseAdaptiveDragPlane && !Keyboard.IsKeyDown(Key.LeftShift); // Don't do this here //if (usingAdaptive) //{ // // Refresh the plane before casting a ray onto it. // // (mousemove will only fire when they actually move the mouse, so the item could be off the plane that _dragPlane knows // // about) // // When not using adaptive, the item needs to be dragged strictly onto the plane from when they first started dragging. But // // adaptive tries to drag the item into other items that are off the plane // //TODO: I think this is a bit flawed. It can cause the drag plane to move perpendicular to itself too easily at times // ChangeDragPlane(); //} #region Fire Ray //NOTE: This was copied from Game.Newt.v2.GameItems.ShipEditor.Editor.ChangeDragHitShape() RayHitTestParameters mouseRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, clickPoint); Point3D?hitPoint; if (_selectedItem.IsUsingSpring) { hitPoint = _dragPlane.CastRay(mouseRay); } else { hitPoint = _dragPlane.CastRay(_dragMouseDownClickRay, _dragMouseDownCenterRay, mouseRay, _camera, _viewport); } #endregion if (hitPoint == null) { return; } Point3D adjustedHitPoint = hitPoint.Value; if (usingAdaptive) { adjustedHitPoint = DragItem_Adaptive(hitPoint.Value); } _dragHistory.Add(adjustedHitPoint); //NOTE: SelectedItem may set the position directly, or apply a spring force toward this point passed in _selectedItem.SetPosition(adjustedHitPoint); #region NOT USED //There is no rotation for a plane //Quaternion? rotationDelta = _dragPlane.GetRotation(clickPoint, hitPoint.Value); //if (rotationDelta != null) //{ // Quaternion newRotation = Quaternion.Multiply(rotationDelta.Value.ToUnit(), _mouseDownDragOrientation); // _selectedItem.Orientation = newRotation; //} #endregion }