/// <summary> /// Создает камеру, которую можно крутить движением мышки /// </summary> /// <param name="eventSource">Control,с которого обрабатываются события </param> /// <param name="cameraLocation">Исходное положение камеры</param> public TrackballCamera(Control eventSource, Frame3D cameraLocation) : base(eventSource.ClientSize.Width / (double)eventSource.ClientSize.Height) { EventSource = eventSource; Vector3 tempLoc = cameraLocation.ToDirectXVector(); _cameraLocation = new Vector3(Math.Abs(tempLoc.X), 0, tempLoc.Z); Angle ang = Geometry.Atan2(tempLoc.Y, tempLoc.X); _rotationMatrix = Matrix.RotationZ(-(float)ang.Radian); _radius = _cameraLocation.Length(); Scale = 1; }
/// <summary> /// По перемещению мышки вычисляет перемешение камеры: /// матрицу для поворота и перемещение по вертикальной оси /// </summary> /// <param name="currentPosition">Положение мышки</param> protected virtual void Track(Point currentPosition) { Vector3 currentPosition3D = ProjectToTrackball( _eventSource.ClientRectangle.Width, _eventSource.ClientRectangle.Height, currentPosition); Vector3 diff = currentPosition3D - _previousPosition3D; _rotationMatrix *= Matrix.RotationZ(diff.X); float tempz = _cameraLocation.Z + diff.Y * 100; var tempx = (float)Math.Sqrt(_radius * _radius - tempz * tempz); if (tempx > 1 && tempz > 0) { _cameraLocation.X = tempx; _cameraLocation.Z = tempz; } _previousPosition3D = currentPosition3D; }
/// <summary> Draws a line. </summary> /// <param name="vecStartPos"> The vector start position. </param> /// <param name="vecEndPos"> The vector end position. </param> /// <param name="width"> The width. </param> /// <param name="color"> The color. </param> public static void DrawLineEx(Vector3 vecStartPos, Vector3 vecEndPos, float width, Color color) { const int numCorners = 20; Vector3 start = new Vector3(0.5f, 0.0f, 0.0f); Vector3 end = new Vector3(-0.5f, 0.0f, 0.0f); if (_lineVertices == null) { _lineVertices = new ColoredVertex[numCorners * 2]; for (int i = 0; i < numCorners; i++) { Vector3 offset = new Vector3(0.0f, (float)Math.Cos((2.0f * Math.PI) / numCorners * i), (float)Math.Sin((2.0f * (float)Math.PI) / numCorners * i)); Vector3 startPoint = start + offset; ColoredVertex startVert = new ColoredVertex(new Vector3(startPoint.X, startPoint.Y, startPoint.Z), color.ToArgb()); _lineVertices[i] = startVert; Vector3 endPoint = end + offset; ColoredVertex endVert = new ColoredVertex(new Vector3(endPoint.X, endPoint.Y, endPoint.Z), color.ToArgb()); _lineVertices[numCorners + i] = endVert; } } if (_lineFaceIndices == null) { _lineFaceIndices = new int[numCorners * 2 * 3]; // The number of faces is the same as the number of corners: 2 tris per face, 3 inds per tri for (int i = 0; i < numCorners; i++) { _lineFaceIndices[i * 6 + 0] = i; // ring 1, vert i _lineFaceIndices[i * 6 + 1] = numCorners + i; // ring 2, vert i _lineFaceIndices[i * 6 + 2] = (i + 1) % numCorners; // ring 1, vert i + 1 _lineFaceIndices[i * 6 + 3] = (i + 1) % numCorners; // ring 1, vert i + 1 _lineFaceIndices[i * 6 + 4] = i == numCorners - 1 ? numCorners : numCorners + i + 1; // ring 2, vert i + 1 _lineFaceIndices[i * 6 + 5] = numCorners + i; // ring 2, vert i } } Vector3 startToEnd = vecEndPos - vecStartPos; Matrix scaling = Matrix.Scaling(Vector3.Distance(vecStartPos, vecEndPos), width / 2, width / 2); Matrix rotationY = Matrix.RotationY(-(float)Math.Asin(startToEnd.Z / Vector3.Distance(vecStartPos, vecEndPos))); Matrix rotationZ = Matrix.RotationZ((float)Math.Atan2(startToEnd.Y, startToEnd.X)); Matrix rotation = Matrix.Multiply(rotationY, rotationZ); Matrix translation = Matrix.Translation(start.X + startToEnd.X / 2, start.Y + startToEnd.Y / 2, start.Z + startToEnd.Z / 2); Matrix world = Matrix.Multiply(Matrix.Multiply(scaling, rotation), translation); Device.SetTransform(TransformState.World, world); var oldDecl = Device.VertexDeclaration; using (var newDecl = ColoredVertex.GetDecl(Device)) { Device.VertexDeclaration = newDecl; Device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, numCorners * 2, numCorners * 2, _lineFaceIndices, Format.Index32, _lineVertices, ColoredVertex.Stride); Device.VertexDeclaration = oldDecl; } }