Ejemplo n.º 1
0
        /// <summary>
        /// Moves the pivot point of a GameObject to a new position provided. The method also preserves the orientations of the children objects. Any errors are reported as exceptions.
        /// </summary>
        /// <param name="forObject"> The objects whose pivot point will be modified. If the provided object is meshless then this method simply changes the position of the GameObject while preserving the transform states of the children objects.</param>
        /// <param name="moveTo"> The new point in space to move the pivot to.</param>
        /// <param name="recalculateNormalsTangents"> Should the mesh normals and tangents be recalculated after pivot modification.</param>
        public static void MovePivot(GameObject forObject, Vector3 moveTo, bool recalculateNormalsTangents)
        {
            if (forObject == null)
            {
                throw new ArgumentNullException("forObject", "You must provide a GameObject to move pivot for.");
            }

            Mesh mesh = SetupMeshForTempChanges(forObject);


            if (mesh != null)
            {
                if (UtilityServicesRuntime.IsBone(forObject.transform))
                {
                    throw new InvalidOperationException("The provided gameobject is a bone used by a SkinnedMeshRenderer. Modifying pivot for such an object can cause mesh distortion.");
                }

                if (UtilityServicesRuntime.IsMorphed(forObject.transform))
                {
                    throw new InvalidOperationException("Morphed objects(Meshes with blendshape animations) are not supported. Pivot modifications on such objects can result in incorrect blend shape animations.");
                }

                if (UtilityServicesRuntime.IsMorphed(forObject.transform))
                {
                    throw new InvalidOperationException("Morphed objects(Meshes with blendshape animations) are not supported. Pivot modifications on such objects can result in incorrect blend shape animations.");
                }
            }


            UtilityServicesRuntime.ChildStateTuple[] childrenStatesBeforePivotMod = UtilityServicesRuntime.SaveChildrenStates(forObject);


            // The object is meshless
            if (mesh == null)
            {
                forObject.transform.position = moveTo;
            }

            else
            {
                Vector3[] vertices = mesh.vertices;

                Vector3 pivotOffsetLocalSpace = forObject.transform.InverseTransformVector(forObject.transform.position - moveTo);

                Matrix4x4 transformationMatrix = Matrix4x4.Translate(pivotOffsetLocalSpace);


                for (int a = 0; a < vertices.Length; a++)
                {
                    vertices[a] = transformationMatrix.MultiplyPoint3x4(vertices[a]);
                }


                mesh.vertices = vertices;    //Assign the vertex array back to the mesh


                if (recalculateNormalsTangents)
                {
                    mesh.RecalculateNormals();
                    mesh.RecalculateTangents();
                }

                mesh.RecalculateBounds();


                forObject.transform.position = moveTo;   // Move the object to the previous position
            }


            UtilityServicesRuntime.RestoreChildrenStates(childrenStatesBeforePivotMod);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Changes the rotation of the pivot point of a GameObject. The method also preserves the orientations of the children objects. Any errors are reported as exceptions. Please note that this operation can result in skewing of the object if it is non uniformly scaled.
        /// </summary>
        /// <param name="forObject"> The objects whose pivot point will be modified. If the provided object is meshless then this method simply changes the rotation of the GameObject.</param>
        /// <param name="newRotation"> The new rotation of the pivot point in world space.</param>
        /// <param name="recalculateNormalsTangents"> Should the mesh normals and tangents be recalculated after pivot modification.</param>
        public static void RotatePivotTo(GameObject forObject, Quaternion newRotation, bool recalculateNormalsTangents)
        {
            if (forObject == null)
            {
                throw new ArgumentNullException("forObject", "You must provide a GameObject to rotate pivot for.");
            }

            Mesh mesh = SetupMeshForTempChanges(forObject);


            if (mesh != null)
            {
                if (UtilityServicesRuntime.IsBone(forObject.transform))
                {
                    throw new InvalidOperationException("The provided gameobject is a bone used by a SkinnedMeshRenderer. Modifying pivot for such an object can cause mesh distortion.");
                }

                if (UtilityServicesRuntime.IsMorphed(forObject.transform))
                {
                    throw new InvalidOperationException("Morphed objects(Meshes with blendshape animations) are not supported. Pivot modifications on such objects can result in incorrect blend shape animations.");
                }

                if (!UtilityServicesRuntime.IsUniformScale(forObject.transform.lossyScale))
                {
                    throw new InvalidOperationException("The selected object has non uniform scaling applied. Rotational modifications of pivots for non uniformly scaled objects can result in mesh skewing. It's best to first uniformly scale such an object before applying rotational modifications to the pivot.");
                }
            }


            UtilityServicesRuntime.ChildStateTuple[] childrenStatesBeforePivotMod = UtilityServicesRuntime.SaveChildrenStates(forObject);


            // The object is meshless
            if (mesh == null)
            {
                forObject.transform.rotation = newRotation;
            }

            else
            {
                GameObject tempObject = new GameObject();
                tempObject.transform.parent   = forObject.transform;
                tempObject.transform.rotation = newRotation;
                Quaternion inverseRotation = Quaternion.Inverse(tempObject.transform.localRotation);


                Quaternion prevRotation = forObject.transform.rotation;
                DestroyImmediate(tempObject);

                Matrix4x4 transformationMatrix = Matrix4x4.Rotate(inverseRotation);

                forObject.transform.rotation = newRotation;

                Vector3[] vertices = mesh.vertices;

                //Debug.Log("submeshes count  " + forObject.GetComponent<MeshFilter>().sharedMesh.subMeshCount + "  vertex count   "  + vertices.Length);


                for (int a = 0; a < vertices.Length; a++)
                {
                    vertices[a] = transformationMatrix.MultiplyPoint3x4(vertices[a]);
                }

                mesh.vertices = vertices;

                if (recalculateNormalsTangents)
                {
                    mesh.RecalculateNormals();
                    mesh.RecalculateTangents();
                }

                mesh.RecalculateBounds();
            }


            UtilityServicesRuntime.RestoreChildrenStates(childrenStatesBeforePivotMod);
        }