Просмотр исходного кода

Improvements to SceneObject transform

Marko Pintera 11 лет назад
Родитель
Сommit
2f7095dbd2

+ 8 - 0
BansheeCore/Include/BsSceneObject.h

@@ -132,6 +132,14 @@ namespace BansheeEngine
 		 */
 		const Vector3& getScale() const { return mScale; }
 
+		/**
+		 * @brief	Sets the world scale of the object.
+		 *
+		 * @note	This will not work properly if this object or any of its parents
+		 *			have non-affine transform matrices.
+		 */
+		void setWorldScale(const Vector3& scale);
+
 		/**
 		 * @brief	Gets world scale of the object.
 		 *

+ 25 - 0
BansheeCore/Source/BsSceneObject.cpp

@@ -155,6 +155,21 @@ namespace BansheeEngine
 		markTfrmDirty();
 	}
 
+	void SceneObject::setWorldScale(const Vector3& scale)
+	{
+		if (mParent != nullptr)
+		{
+			Matrix4 parentTfrm = mParent->getWorldTfrm();
+			parentTfrm.inverseAffine();
+
+			mScale = parentTfrm.multiplyDirection(scale);
+		}
+		else
+			mScale = scale;
+
+		markTfrmDirty();
+	}
+
 	const Vector3& SceneObject::getWorldPosition() const
 	{ 
 		if (!isCachedWorldTfrmUpToDate())
@@ -357,6 +372,11 @@ namespace BansheeEngine
 
 		if(mParent == nullptr || mParent != parent)
 		{
+			// Make sure the object keeps its world coordinates
+			Vector3 worldPos = getWorldPosition();
+			Quaternion worldRot = getWorldRotation();
+			Vector3 worldScale = getWorldScale();
+
 			if(mParent != nullptr)
 				mParent->removeChild(mThisHandle);
 
@@ -364,6 +384,11 @@ namespace BansheeEngine
 				parent->addChild(mThisHandle);
 
 			mParent = parent;
+
+			setWorldPosition(worldPos);
+			setWorldRotation(worldRot);
+			setWorldScale(worldScale);
+
 			markTfrmDirty();
 		}
 	}

+ 1 - 1
BansheeEditor/Source/BsSceneViewHandler.cpp

@@ -134,7 +134,7 @@ namespace BansheeEngine
 			offset.y = -maxHeight;
 
 		windowPos += offset;
-		
+
 		Vector2I wrappedScreenPos = parentWindow->windowToScreenPos(windowPos);
 		Cursor::instance().setScreenPosition(wrappedScreenPos);
 

+ 13 - 2
BansheeUtility/Include/BsMatrix4.h

@@ -345,7 +345,7 @@ namespace BansheeEngine
         }
 
         /**
-         * @brief	Transform a 3D vector by this matrix.
+         * @brief	Transform a 3D point by this matrix.
          * 			
          * @note	Matrix must be affine, if it is not use "multiply" method.
          */
@@ -392,7 +392,7 @@ namespace BansheeEngine
         }
 
         /**
-         * @brief	Transform a 3D vector by this matrix.  
+         * @brief	Transform a 3D point by this matrix.  
          *
          * @note	w component of the vector is assumed to be 1. After transformation all components
          * 			are projected back so that w remains 1.
@@ -412,6 +412,17 @@ namespace BansheeEngine
             return r;
         }
 
+		/**
+         * @brief	Transform a 3D direction by this matrix.
+         */
+        Vector3 multiplyDirection(const Vector3& v) const
+        {
+            return Vector3(
+                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, 
+                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z,
+                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z);
+        }
+
         /**
          * @brief	Transform a 4D vector by this matrix.  
          *

+ 3 - 5
MBansheeEditor/Scene/MoveHandle.cs

@@ -100,12 +100,10 @@ namespace BansheeEditor
             float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
 
             // Draw 1D arrows
-            Color axisHover = new Color(0.8f, 0.8f, 0.8f, 1.0f);
-
             if (xAxis.State == HandleSlider.StateType.Active)
                 HandleDrawing.SetColor(Color.White);
             else if(xAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.SetColor(Color.Red * axisHover);
+                HandleDrawing.SetColor(Color.BansheeOrange);
             else
                 HandleDrawing.SetColor(Color.Red);
 
@@ -116,7 +114,7 @@ namespace BansheeEditor
             if (yAxis.State == HandleSlider.StateType.Active)
                 HandleDrawing.SetColor(Color.White);
             else if (yAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.SetColor(Color.Green * axisHover);
+                HandleDrawing.SetColor(Color.BansheeOrange);
             else
                 HandleDrawing.SetColor(Color.Green);
 
@@ -127,7 +125,7 @@ namespace BansheeEditor
             if (zAxis.State == HandleSlider.StateType.Active)
                 HandleDrawing.SetColor(Color.White);
             else if (zAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.SetColor(Color.Blue * axisHover);
+                HandleDrawing.SetColor(Color.BansheeOrange);
             else
                 HandleDrawing.SetColor(Color.Blue);
 

+ 1 - 24
MBansheeEditor/Scene/RotateHandle.cs

@@ -10,8 +10,6 @@ namespace BansheeEditor
         private HandleSliderDisc yAxis;
         private HandleSliderDisc zAxis;
 
-        private HandleSliderDisc freeAxis;
-
         public Quaternion Delta
         {
             get { return delta; }
@@ -21,8 +19,7 @@ namespace BansheeEditor
         {
             return xAxis.State == HandleSlider.StateType.Active ||
                     yAxis.State == HandleSlider.StateType.Active ||
-                    zAxis.State == HandleSlider.StateType.Active ||
-                    freeAxis.State == HandleSlider.StateType.Active;
+                    zAxis.State == HandleSlider.StateType.Active;
         }
 
         public RotateHandle()
@@ -30,7 +27,6 @@ namespace BansheeEditor
             xAxis = new HandleSliderDisc(this, Vector3.xAxis, 1.0f);
             yAxis = new HandleSliderDisc(this, Vector3.yAxis, 1.0f);
             zAxis = new HandleSliderDisc(this, Vector3.zAxis, 1.0f);
-            freeAxis = new HandleSliderDisc(this, Vector3.zAxis, 1.0f);
         }
 
         protected override void PreInput()
@@ -39,13 +35,9 @@ namespace BansheeEditor
             yAxis.Position = position;
             zAxis.Position = position;
 
-            freeAxis.Position = position;
-            freeAxis.Rotation = EditorApplication.SceneViewCamera.sceneObject.Rotation;
-
             xAxis.SetCutoffPlane(GetXStartAngle(), true);
             yAxis.SetCutoffPlane(GetYStartAngle(), true);
             zAxis.SetCutoffPlane(GetZStartAngle(), true);
-            freeAxis.SetCutoffPlane(0.0f, false);
         }
 
         protected override void PostInput()
@@ -72,14 +64,6 @@ namespace BansheeEditor
             delta = Quaternion.FromAxisAngle(GetXDir(), xValue) * delta;
             delta = Quaternion.FromAxisAngle(GetYDir(), yValue) * delta;
             delta = Quaternion.FromAxisAngle(GetZDir(), zValue) * delta;
-
-            if (freeAxis.State == HandleSlider.StateType.Active)
-            {
-                Matrix4 cameraToWorld = EditorApplication.SceneViewCamera.ViewMatrixInverse;
-
-                Vector3 rotDir = cameraToWorld.MultiplyAffine(new Vector3(-Input.PointerDelta.y, -Input.PointerDelta.x, 0));
-                delta = Quaternion.FromAxisAngle(rotDir.Normalized, Input.PointerDelta.Magnitude)*delta;
-            }
         }
 
         protected override void Draw()
@@ -127,13 +111,6 @@ namespace BansheeEditor
                 HandleDrawing.DrawArc(Vector3.zero, GetZDir(), 1.0f, zAxis.StartAngle, zAxis.Delta, handleSize);
 
             // Draw free rotate handle
-            if (freeAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.SetColor(Color.White);
-            else if (freeAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.SetColor(Color.BansheeOrange);
-            else
-                HandleDrawing.SetColor(Color.White);
-
             //// Rotate it so it always faces the camera, and move it forward a bit to always render in front
             Vector3 freeHandleNormal = EditorApplication.SceneViewCamera.sceneObject.Rotation.Rotate(GetZDir());
             Vector3 offset = freeHandleNormal*0.1f;

+ 2 - 56
TODO.txt

@@ -7,8 +7,8 @@ Possibly set up automatic refresh in debug mode after initialization? As an ad-h
 
 <<<<<<Handles>>>>>>>>
 
-Free rotate doesn't really work
 When scaling using center make sure to offset the object before scale
+Handles should probably not having shading, or have better shading.
 
 Rotate handle:
  - How to handle local/global with rotate handle?
@@ -17,9 +17,6 @@ Rotate handle:
 
 Ideally free scale handle indicator should always render and be interactable and never be hidden by axis scale indicators (Not high priority)
 
-Cursor wrap only works when cursor moves really slowly over the border, and even then it's spotty
-When changing handle types they do not refresh until you click on the scene view
-
 <<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Register it in its meta file
@@ -29,8 +26,6 @@ When changing handle types they do not refresh until you click on the scene view
 
 Other:
 Window resize end callback
-Add cutoff plane when rendering discs for rotation handle.
-There seems to be a delay when changing GUI element sprite textures (like 1 frame there is no texture at all)
 
 I can get mono errors by checking g_print calls in goutput.c
  - Calling thunks incorrectly can cause those weird errors with no real callstack
@@ -53,64 +48,15 @@ Set up a default layout and save it
 Need a way to drag and drop items from Scene tree view to Scene view
 
 AFTER I have scene widget in C#:
- - Implement free move handle and remaining handles
  - Test custom handles from C#
  - Test handle snapping
 
-IMPLEMENT SELECTION RENDERING
-
 IMPROVE SceneGrid LOOK - Use the shader created in Unity
 
-----------------------------------------------------------------------
-Handles
-
-SliderLine - position, direction, length
-  - When initially activated it records position nearest so the line as the starting point
-  - Further mouse dragging also finds nearest position to the line
-  - Difference between those two results in a float value (how much to move along direction from position to reach new position)
-  - Slider line has a capsule + sphere collider size of which can be set manually
-
-SliderPlane - position, normal, size
-  - Similar to line slider only the direction is determined dynamically as well as distance
-  - Outputs a Vector2 (direction * distance moved)
-  - A OOB is used as a collider
-
-SliderDisc - position, normal, radius
-  - When initially activated it records position nearest so the disc as the starting point
-  - Further movement calculates the dynamic direction from the starting point to the current point on the plane the disc lies on
-  - Distance along that direction is returned as amount of movement (similar to line slider)
-  - Outputs a single float
-  - A torus is used as a collider
-
-Free move/rotate/scale handles need to exist as well
- - Scale is easy, just perform uniform scale. Use SliderPlane oriented towards camera
- - Move also use SliderPlane oriented towards camera
- - Rotation use SliderDisc oriented towards camera
-
-----------------------------------------------------
-STAGE 1
-
-CONCRETE TODO:
-HandleSliderPlane/HandleSliderDisc
- - update() implementation
-
-----------------------------------------------------
-STAGE 2
-Implement RotateHandle & ScaleHandle in C#
- - Nearest point to disc/arc code
-Add 2D move and scale
-Add free move, free rotate, free scale functionality
-Handles that remain the same size regardless of distance from camera
- - For both drawing and collision
-
- More complex types for drawing like DrawArrow in HandleDrawManager
-
 ----------------------------------------------------------------------
 SelectionRenderer
 
 Retrieve a list of selected objects from SelectionManager
 Find ones with Renderable components
 Retrieve Meshes, and world transforms from them
-Draw that same mesh with either a wireframe or a grayed out shader with a slight depth bias
-
----------------------------------------------------------------------
+Draw that same mesh with either a wireframe or a grayed out shader with a slight depth bias