public void Draw(Matrix4x4 viewProjection) { if (!DrawGizmo) { return; } bool upside = Orientation == GizmoOrientation.UpsideDown; _device.SetRasterizerState(_device.RasterizerStates.CullNone); var solidEffect = _effect; GizmoMode highlight = _mode == GizmoMode.None ? _hoveredMode : _mode; // Rotation if (SupportRotationX | SupportRotationY | SupportRotationZ) { // Setup torus model float requiredTorusRadius = LineThickness * 0.5f / Size; if (_torusRadius != requiredTorusRadius) { _torus?.Dispose(); _torus = GeometricPrimitive.Torus.New(_device, 1.0f, requiredTorusRadius, 48, _lineRadiusTesselation); _torusRadius = requiredTorusRadius; } _torus.SetupForRendering(_device); // Rotation Y if (SupportRotationY) { var model = Matrix4x4.CreateScale(Size * 2.0f) * RotateMatrixY * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_yAxisColor + (highlight == GizmoMode.RotateY ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _torus.IndexBuffer.ElementCount); } // Rotation X if (SupportRotationX) { var model = Matrix4x4.CreateScale(Size * 2.0f) * Matrix4x4.CreateRotationZ((float)Math.PI / 2.0f) * RotateMatrixX * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_xAxisColor + (highlight == GizmoMode.RotateX ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _torus.IndexBuffer.ElementCount); } // Rotation Z if (SupportRotationZ) { var model = Matrix4x4.CreateScale(Size * 2.0f) * Matrix4x4.CreateRotationX((float)Math.PI / 2.0f) * RotateMatrixZ * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_zAxisColor + (highlight == GizmoMode.RotateZ ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _torus.IndexBuffer.ElementCount); } } // Scale if (SupportScale) { _cylinder.SetupForRendering(_device); // X axis { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness * 1.1f, (upside ? -Size : Size) / 2.0f, LineThickness * 1.1f)) * Matrix4x4.CreateRotationZ(-(float)Math.PI / 2.0f) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_xAxisColor + (highlight == GizmoMode.ScaleX ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } // Y axis { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness * 1.1f, (upside ? -Size : Size) / 2.0f, LineThickness * 1.1f)) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_yAxisColor + (highlight == GizmoMode.ScaleY ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } // Z axis { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness * 1.1f, (upside ? -Size : Size) / 2.0f, LineThickness * 1.1f)) * Matrix4x4.CreateRotationX(-(float)Math.PI / 2.0f) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_zAxisColor + (highlight == GizmoMode.ScaleZ ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } _cube.SetupForRendering(_device); // X axis scale { var model = Matrix4x4.CreateScale(ScaleCubeSize) * Matrix4x4.CreateTranslation(Position + Vector3.UnitX * (upside ? -Size : Size) / 2.0f); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_xAxisColor + (highlight == GizmoMode.ScaleX ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cube.IndexBuffer.ElementCount); } // Y axis scale { var model = Matrix4x4.CreateScale(ScaleCubeSize) * Matrix4x4.CreateTranslation(Position + Vector3.UnitY * (upside ? -Size : Size) / 2.0f); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_yAxisColor + (highlight == GizmoMode.ScaleY ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cube.IndexBuffer.ElementCount); } // Z axis scale { var model = Matrix4x4.CreateScale(ScaleCubeSize) * Matrix4x4.CreateTranslation(Position - Vector3.UnitZ * (upside ? -Size : Size) / 2.0f); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_zAxisColor + (highlight == GizmoMode.ScaleZ ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cube.IndexBuffer.ElementCount); } } // Translation { _cylinder.SetupForRendering(_device); // X axis if (SupportTranslateX) { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness, (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, LineThickness)) * Matrix4x4.CreateRotationZ(-(float)Math.PI / 2.0f) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_xAxisColor + (highlight == GizmoMode.TranslateX ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } // Y axis if (SupportTranslateY) { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness, (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, LineThickness)) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_yAxisColor + (highlight == GizmoMode.TranslateY ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } // Z axis if (SupportTranslateZ) { var model = Matrix4x4.CreateTranslation(new Vector3(0.0f, 0.5f, 0.0f)) * Matrix4x4.CreateScale(new Vector3(LineThickness, (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, LineThickness)) * Matrix4x4.CreateRotationX(-(float)Math.PI / 2.0f) * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_zAxisColor + (highlight == GizmoMode.TranslateZ ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cylinder.IndexBuffer.ElementCount); } _cone.SetupForRendering(_device); // X axis translation if (SupportTranslateX) { var model = Matrix4x4.CreateRotationY((float)(upside ? -Math.PI * 1.5f : -Math.PI * 0.5f)) * Matrix4x4.CreateScale(TranslationConeSize) * Matrix4x4.CreateTranslation(Position + (Vector3.UnitX + new Vector3(0.1f, 0, 0)) * ((upside ? -Size : Size) * _arrowHeadOffsetMultiplier)); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_xAxisColor + (highlight == GizmoMode.TranslateX ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cone.IndexBuffer.ElementCount); } // Y axis translation if (SupportTranslateY) { var model = Matrix4x4.CreateRotationX((float)(upside ? Math.PI * 1.5f : Math.PI * 0.5f)) * Matrix4x4.CreateScale(TranslationConeSize) * Matrix4x4.CreateTranslation(Position + (Vector3.UnitY + new Vector3(0, 0.1f, 0)) * ((upside ? -Size : Size) * _arrowHeadOffsetMultiplier)); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_yAxisColor + (highlight == GizmoMode.TranslateY ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cone.IndexBuffer.ElementCount); } // Z axis translation if (SupportTranslateZ) { var model = Matrix4x4.CreateRotationY((float)(upside ? Math.PI : 0.0f)) * Matrix4x4.CreateScale(TranslationConeSize) * Matrix4x4.CreateTranslation(Position - (Vector3.UnitZ + new Vector3(0, 0, 0.1f)) * ((upside ? -Size : Size) * _arrowHeadOffsetMultiplier)); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(_zAxisColor + (highlight == GizmoMode.TranslateZ ? _hoveredAddition : new Vector4())); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _cone.IndexBuffer.ElementCount); } } // All time geometry { /*_device.SetVertexBuffer(_cube.VertexBuffer); * _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _cube.VertexBuffer)); * _device.SetIndexBuffer(_cube.IndexBuffer, _cube.IsIndex32Bits); * * // center cube * { * var model = Matrix4x4.CreateScale(CentreCubeSize) * Matrix4x4.CreateTranslation(Position); * solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); * solidEffect.Parameters["Color"].SetValue(_centerColor); * solidEffect.CurrentTechnique.Passes[0].Apply(); * * _device.DrawIndexed(PrimitiveType.TriangleList, _cube.IndexBuffer.ElementCount); * }*/ } _device.SetRasterizerState(_device.RasterizerStates.CullBack); // Rotation display vertices switch (_mode) { case GizmoMode.RotateY: case GizmoMode.RotateX: case GizmoMode.RotateZ: // Figure out relevant angle float startAngle; float endAngle; float lastMouseAngle; Matrix4x4 baseMatrix; Vector4 color; switch (_mode) { case GizmoMode.RotateY: startAngle = _rotationPickAngle; endAngle = RotationY - _rotationPickAngleOffset; lastMouseAngle = _rotationLastMouseAngle; baseMatrix = RotateMatrixY; color = _yAxisColor; break; case GizmoMode.RotateX: startAngle = -((float)Math.PI * 0.5f) - _rotationPickAngle; endAngle = -((float)Math.PI * 0.5f) - (RotationX - _rotationPickAngleOffset); lastMouseAngle = -((float)Math.PI * 0.5f) - _rotationLastMouseAngle; baseMatrix = Matrix4x4.CreateRotationZ((float)Math.PI / 2.0f) * RotateMatrixX; color = _xAxisColor; break; case GizmoMode.RotateZ: startAngle = (float)Math.PI + _rotationPickAngle; endAngle = (float)Math.PI + RotationZ - _rotationPickAngleOffset; lastMouseAngle = (float)Math.PI + _rotationLastMouseAngle; baseMatrix = Matrix4x4.CreateRotationX((float)Math.PI / 2.0f) * RotateMatrixZ; color = _zAxisColor; break; default: throw new NotImplementedException(); } { // Choose shortest path float shortestAngle = endAngle - startAngle; shortestAngle = (float)(shortestAngle - Math.Round(shortestAngle / (Math.PI * 2)) * (Math.PI * 2)); endAngle = startAngle + shortestAngle; } if (startAngle > endAngle) { float temp = startAngle; startAngle = endAngle; endAngle = temp; } // Build rotation geometry var rotationHelperGeometry = new SolidVertex[_rotationTrianglesCount * 3 + 2]; float angleStep = (endAngle - startAngle) / _rotationTrianglesCount; var middleVertex = new SolidVertex(new Vector3()); var lastVertex = new SolidVertex(new Vector3((float)Math.Cos(startAngle), 0, (float)-Math.Sin(startAngle))); for (int i = 0; i < _rotationTrianglesCount; ++i) { float currentAngle = startAngle + (i + 1) * angleStep; var currentVertex = new SolidVertex(new Vector3((float)Math.Cos(currentAngle), 0, (float)-Math.Sin(currentAngle))); rotationHelperGeometry[i * 3 + 0] = middleVertex; rotationHelperGeometry[i * 3 + 1] = lastVertex; rotationHelperGeometry[i * 3 + 2] = currentVertex; lastVertex = currentVertex; } rotationHelperGeometry[_rotationTrianglesCount * 3] = new SolidVertex(new Vector3( _rotationLastMouseRadius / Size * (float)Math.Cos(lastMouseAngle), 0, _rotationLastMouseRadius / Size * (float)-Math.Sin(lastMouseAngle))); rotationHelperGeometry[_rotationTrianglesCount * 3 + 1] = middleVertex; _rotationHelperGeometry.SetData(rotationHelperGeometry); // Draw _device.SetRasterizerState(_device.RasterizerStates.CullNone); _device.SetVertexBuffer(_rotationHelperGeometry); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _rotationHelperGeometry)); var model = Matrix4x4.CreateScale(Size) * baseMatrix * Matrix4x4.CreateTranslation(Position); solidEffect.Parameters["ModelViewProjection"].SetValue((model * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(color * _rotationAlpha); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.Draw(PrimitiveType.TriangleList, _rotationTrianglesCount * 3); solidEffect.Parameters["Color"].SetValue(Vector4.One); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.SetRasterizerState(_rasterizerWireframe); _device.Draw(PrimitiveType.LineList, 2, _rotationTrianglesCount * 3); // FIXME: Temporary fix for text corruption problem! Remove when SharpDX is not used. _device.SetRasterizerState(_device.RasterizerStates.Default); break; } }