Ejemplo n.º 1
0
        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;
            }
        }