} // Update #endregion #region Render Gizmo For Picker /// <summary> /// Render the gizmo to the picker. /// </summary> private void RenderGizmoForPicker(GameObject3D gizmoCamera) { // Calculate the center, scale and orientation of the gizmo. Vector3 center; Quaternion orientation; float scale; GizmoScaleCenterOrientation(selectedObject, gizmoCamera, out scale, out center, out orientation); // Calculate the gizmo matrix. Matrix transformationMatrix = Matrix.CreateScale(scale); transformationMatrix *= Matrix.CreateFromQuaternion(orientation); transformationMatrix *= Matrix.CreateTranslation(center); vertices[0] = Vector3.Transform(new Vector3(0, 0, 0), transformationMatrix); vertices[1] = Vector3.Transform(new Vector3(1, 0, 0), transformationMatrix); vertices[2] = Vector3.Transform(new Vector3(0, 1, 0), transformationMatrix); vertices[3] = Vector3.Transform(new Vector3(0, 0, 1), transformationMatrix); vertices[4] = Vector3.Transform(new Vector3(1, 1, 0), transformationMatrix); vertices[5] = Vector3.Transform(new Vector3(0, 1, 1), transformationMatrix); vertices[6] = Vector3.Transform(new Vector3(1, 0, 1), transformationMatrix); planeRedGreen.Transform.LocalMatrix = transformationMatrix; planeGreenBlue.Transform.LocalMatrix = transformationMatrix; planeBlueRed.Transform.LocalMatrix = transformationMatrix; Picker.RenderObjectToPicker(planeRedGreen, new Color(255, 255, 0)); Picker.RenderObjectToPicker(planeGreenBlue, new Color(0, 255, 255)); Picker.RenderObjectToPicker(planeBlueRed, new Color(255, 0, 255)); // Render a second time but from the other side. planeRedGreenInv.Transform.LocalMatrix = transformationMatrix; planeGreenBlueInv.Transform.LocalMatrix = transformationMatrix; planeBlueRedInv.Transform.LocalMatrix = transformationMatrix; Picker.RenderObjectToPicker(planeRedGreenInv, new Color(255, 255, 0)); Picker.RenderObjectToPicker(planeGreenBlueInv, new Color(0, 255, 255)); Picker.RenderObjectToPicker(planeBlueRedInv, new Color(255, 0, 255)); EngineManager.Device.Clear(ClearOptions.DepthBuffer, Color.White, 1, 0); // Update Axis Lines lines.LineRenderer.Vertices[0] = new VertexPositionColor(vertices[0], Color.Red); lines.LineRenderer.Vertices[1] = new VertexPositionColor(vertices[1], Color.Red); lines.LineRenderer.Vertices[2] = new VertexPositionColor(vertices[0], new Color(0, 255, 0)); lines.LineRenderer.Vertices[3] = new VertexPositionColor(vertices[2], new Color(0, 255, 0)); lines.LineRenderer.Vertices[4] = new VertexPositionColor(vertices[0], Color.Blue); lines.LineRenderer.Vertices[5] = new VertexPositionColor(vertices[3], Color.Blue); Picker.RenderObjectToPicker(lines); // Update Cones redCone.Transform.LocalMatrix = Matrix.Identity; redCone.Transform.LocalPosition = new Vector3(1, 0, 0); redCone.Transform.Rotate(new Vector3(0, 0, -90)); redCone.Transform.LocalMatrix = redCone.Transform.LocalMatrix * transformationMatrix; Picker.RenderObjectToPicker(redCone, Color.Red); greenCone.Transform.LocalMatrix = Matrix.Identity; greenCone.Transform.LocalPosition = new Vector3(0, 1, 0); greenCone.Transform.LocalMatrix = greenCone.Transform.LocalMatrix * transformationMatrix; Picker.RenderObjectToPicker(greenCone, new Color(0, 255, 0)); // Color.Green is not 0, 255, 0 blueCone.Transform.LocalMatrix = Matrix.Identity; blueCone.Transform.LocalPosition = new Vector3(0, 0, 1); blueCone.Transform.Rotate(new Vector3(90, 0, 0)); blueCone.Transform.LocalMatrix = blueCone.Transform.LocalMatrix * transformationMatrix; Picker.RenderObjectToPicker(blueCone, Color.Blue); Vector3 screenPositions = EngineManager.Device.Viewport.Project(vertices[0], gizmoCamera.Camera.ProjectionMatrix, gizmoCamera.Camera.ViewMatrix, Matrix.Identity); planeAll.LineRenderer.Vertices[0] = new VertexPositionColor(new Vector3((int)screenPositions.X - RegionSize / 2, (int)screenPositions.Y - RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[1] = new VertexPositionColor(new Vector3((int)screenPositions.X + RegionSize / 2, (int)screenPositions.Y - RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[2] = new VertexPositionColor(new Vector3((int)screenPositions.X + RegionSize / 2, (int)screenPositions.Y - RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[3] = new VertexPositionColor(new Vector3((int)screenPositions.X + RegionSize / 2, (int)screenPositions.Y + RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[4] = new VertexPositionColor(new Vector3((int)screenPositions.X + RegionSize / 2, (int)screenPositions.Y + RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[5] = new VertexPositionColor(new Vector3((int)screenPositions.X - RegionSize / 2, (int)screenPositions.Y + RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[6] = new VertexPositionColor(new Vector3((int)screenPositions.X - RegionSize / 2, (int)screenPositions.Y + RegionSize / 2, 0), Color.White); planeAll.LineRenderer.Vertices[7] = new VertexPositionColor(new Vector3((int)screenPositions.X - RegionSize / 2, (int)screenPositions.Y - RegionSize / 2, 0), Color.White); Picker.RenderObjectToPicker(planeAll, Color.White); } // RenderGizmoForPicker
} // DisableGizmo #endregion #region Update /// <summary> /// Update. /// </summary> internal void Update(GameObject3D gizmoCamera, Control clientArea) { #region Active if (Active) { // If the manipulation is over... if (!Mouse.LeftButtonPressed) { Active = false; // Store new previous matrix. if (selectedObjects[0].Transform.LocalMatrix != selectedObjectsLocalMatrix[0]) { using (Transaction.Create()) { for (int i = 0; i < selectedObjects.Count; i++) { // I store the action on the undo system. It seems complex. But it is pretty simple actually. Matrix oldMatrix = selectedObjectsLocalMatrix[i]; Matrix newMatrix = selectedObjects[i].Transform.LocalMatrix; GameObject3D gameObject3D = selectedObjects[i]; ActionManager.CallMethod( // Redo delegate { gameObject3D.Transform.LocalMatrix = newMatrix; }, // Undo delegate { gameObject3D.Transform.LocalMatrix = oldMatrix; }); } } } } // Transformate object... else { Vector2 transformationAmount; Vector3 translation = Vector3.Zero; // First we have to know how much to move the object in each axis. if (redAxisSelected) { Calculate2DMouseDirection(selectedObject, gizmoCamera, new Vector3(1, 0, 0), out transformationAmount); translation.X = (Mouse.DeltaX * transformationAmount.X / 100.0f); translation.X += (Mouse.DeltaY * transformationAmount.Y / 100.0f); } if (greenAxisSelected) { Calculate2DMouseDirection(selectedObject, gizmoCamera, new Vector3(0, 1, 0), out transformationAmount); translation.Y = (Mouse.DeltaX * transformationAmount.X / 100.0f); translation.Y += (Mouse.DeltaY * transformationAmount.Y / 100.0f); } if (blueAxisSelected) { Calculate2DMouseDirection(selectedObject, gizmoCamera, new Vector3(0, 0, 1), out transformationAmount); translation.Z = (Mouse.DeltaX * transformationAmount.X / 100.0f); translation.Z += (Mouse.DeltaY * transformationAmount.Y / 100.0f); } // Calculate the scale to do transformation proportional to the camera distance to the object. // The calculations are doing once from only one object to move everything at the same rate. Vector3 center; Quaternion orientation; float scale; GizmoScaleCenterOrientation(selectedObject, gizmoCamera, out scale, out center, out orientation); // Transform each object. foreach (GameObject3D gameObject3D in selectedObjects) { gameObject3D.Transform.Translate(translation * scale, Space == SpaceMode.Local ? Components.Space.Local : Components.Space.World); } } if (Keyboard.KeyJustPressed(Keys.Escape)) { Active = false; // Revert transformation to all selected objects. for (int i = 0; i < selectedObjects.Count; i++) { selectedObjects[i].Transform.LocalMatrix = selectedObjectsLocalMatrix[i]; } } } #endregion #region Inactive else { if (!Keyboard.KeyPressed(Keys.LeftAlt) && !Keyboard.KeyPressed(Keys.RightAlt)) { // If we press the left mouse button the manipulator activates. if (Mouse.LeftButtonJustPressed) { Active = true; // Stores initial matrix because maybe the user press escape; i.e. maybe he cancel the transformation. for (int i = 0; i < selectedObjects.Count; i++) { selectedObjectsLocalMatrix[i] = selectedObjects[i].Transform.LocalMatrix; } } // Perform a pick around the mouse pointer. Viewport viewport = new Viewport(gizmoCamera.Camera.Viewport.X + clientArea.ControlLeftAbsoluteCoordinate, gizmoCamera.Camera.Viewport.Y + clientArea.ControlTopAbsoluteCoordinate, gizmoCamera.Camera.Viewport.Width, gizmoCamera.Camera.Viewport.Height); Picker.BeginManualPicking(gizmoCamera.Camera.ViewMatrix, gizmoCamera.Camera.ProjectionMatrix, viewport); RenderGizmoForPicker(gizmoCamera); Color[] colorArray = Picker.EndManualPicking(new Rectangle(Mouse.Position.X - 5, Mouse.Position.Y - 5, RegionSize, RegionSize)); #region Find Selected Axis redAxisSelected = true; greenAxisSelected = true; blueAxisSelected = true; bool allAxis = false; for (int i = 0; i < RegionSize * RegionSize; i++) { // This is the order of preference: // 1) All axis. // 2) 1 axis. // 3) 2 axis. if (redAxisSelected && greenAxisSelected && blueAxisSelected) { // X and Y axis. if (colorArray[i].R == 255 && colorArray[i].G == 255 && colorArray[i].B == 0) { redAxisSelected = true; greenAxisSelected = true; blueAxisSelected = false; } // X and Z axis. if (colorArray[i].R == 255 && colorArray[i].G == 0 && colorArray[i].B == 255) { redAxisSelected = true; greenAxisSelected = false; blueAxisSelected = true; } // Y and Z axis. if (colorArray[i].R == 0 && colorArray[i].G == 255 && colorArray[i].B == 255) { redAxisSelected = false; greenAxisSelected = true; blueAxisSelected = true; } } // X axis. if (colorArray[i].R == 255 && colorArray[i].G == 0 && colorArray[i].B == 0) { redAxisSelected = true; greenAxisSelected = false; blueAxisSelected = false; } // Y axis. if (colorArray[i].R == 0 && colorArray[i].G == 255 && colorArray[i].B == 0) { redAxisSelected = false; greenAxisSelected = true; blueAxisSelected = false; } // Z axis. if (colorArray[i].R == 0 && colorArray[i].G == 0 && colorArray[i].B == 255) { redAxisSelected = false; greenAxisSelected = false; blueAxisSelected = true; } // All axis. if (colorArray[i].R == 255 && colorArray[i].G == 255 && colorArray[i].B == 255) { redAxisSelected = true; greenAxisSelected = true; blueAxisSelected = true; allAxis = true; i = RegionSize * RegionSize; // Or break. } } if (redAxisSelected && greenAxisSelected && blueAxisSelected && !allAxis) { redAxisSelected = false; greenAxisSelected = false; blueAxisSelected = false; } #endregion } else { redAxisSelected = false; greenAxisSelected = false; blueAxisSelected = false; } } #endregion } // Update