Exemplo n.º 1
0
        /// <summary>
        /// Snap the prefab to ground (y-axis). Sets the prefab position to 0 on y-axis.
        /// If isConsiderPrefabExtents is true, set ground to be the bottom of the prefab
        /// rather than its pivot point.
        /// NOTE: Currently doesn't consider scaling.
        /// </summary>
        /// <param name="isConsiderPrefabExtents"></param>
        private void SnapToGround(bool isConsiderPrefabExtents = false)
        {
            if (lbGroupMember != null && lbGroupDesignerItem != null)
            {
                // Default
                lbGroupMember.minOffsetY = 0f;
                lbGroupMember.maxOffsetY = 0f;

                if (isConsiderPrefabExtents && lbGroupMember.prefab != null && lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.Prefab)
                {
                    // Need to reset y value for GetBounds to work correctly
                    Vector3 tempPos = lbGroupMember.prefab.transform.position;
                    tempPos.y = 0f;
                    lbGroupMember.prefab.transform.position = tempPos;

                    Bounds bounds = LBMeshOperations.GetBounds(lbGroupMember.prefab.transform, false, true);
                    if (bounds.extents.y != 0f)
                    {
                        // bounds.extents.y is half the height of the prefab.
                        lbGroupMember.minOffsetY = bounds.extents.y - bounds.center.y;
                        lbGroupMember.maxOffsetY = lbGroupMember.minOffsetY;
                    }
                }

                lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember);
                LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow));
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Add a zone at the same location as an object/prefab using its extents.
        /// NOTE: Rectangular zones cannot be rotated, so only width and length can be switched
        /// </summary>
        private void AddZoneToObject()
        {
            if (lbGroup != null && lbGroupMember != null && lbGroupDesignerItem != null && lbGroupMember.prefab != null && lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.Prefab)
            {
                // Need to reset postion for GetBounds to work correctly
                Vector3 tempPos = lbGroupMember.prefab.transform.position;
                lbGroupMember.prefab.transform.position = Vector3.zero;
                Bounds bounds = LBMeshOperations.GetBounds(lbGroupMember.prefab.transform, false, true);
                lbGroupMember.prefab.transform.position = tempPos;

                if (bounds.extents.x != 0f && bounds.extents.z != 0f && lbGroup.maxClearingRadius > 0f)
                {
                    LBGroupZone lbGroupZone = new LBGroupZone();
                    if (lbGroupZone != null)
                    {
                        if (bounds.extents.x == bounds.extents.z)
                        {
                            lbGroupZone.zoneType     = LBGroupZone.LBGroupZoneType.circle;
                            lbGroupZone.centrePointX = lbGroupMember.minOffsetX / lbGroup.maxClearingRadius;
                            lbGroupZone.centrePointZ = lbGroupMember.minOffsetZ / lbGroup.maxClearingRadius;
                            lbGroupZone.width        = (bounds.extents.x - bounds.center.x) / lbGroup.maxClearingRadius;
                            lbGroupZone.length       = lbGroupZone.width;
                        }
                        else
                        {
                            lbGroupZone.zoneType     = LBGroupZone.LBGroupZoneType.rectangle;
                            lbGroupZone.centrePointX = lbGroupMember.minOffsetX / lbGroup.maxClearingRadius;
                            lbGroupZone.centrePointZ = lbGroupMember.minOffsetZ / lbGroup.maxClearingRadius;
                            lbGroupZone.width        = (bounds.extents.x - bounds.center.x) * 2f / lbGroup.maxClearingRadius;
                            lbGroupZone.length       = (bounds.extents.z - bounds.center.z) * 2f / lbGroup.maxClearingRadius;

                            float rotationY = lbGroupDesignerItem.transform.rotation.eulerAngles.y;

                            // Get the absolute rotation on y-axis
                            if (rotationY < 0)
                            {
                                rotationY = -rotationY;
                            }

                            // cater for rotation by switching width and length
                            if ((rotationY > 45f && rotationY < 135f) || (rotationY > 225f && rotationY < 315f))
                            {
                                float width = lbGroupZone.width;
                                lbGroupZone.width  = lbGroupZone.length;
                                lbGroupZone.length = width;
                            }
                        }

                        lbGroupZone.zoneName = lbGroupMember.prefab.name + " zone";
                        lbGroup.zoneList.Add(lbGroupZone);
                    }
                }

                LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow));
            }
        }
        // Mesh Operations Class

        #region Submesh Methods

        /// <summary>
        /// Create a new mesh from a submesh of baseMesh with index submeshIndex
        /// </summary>
        public static Mesh CreateMeshFromSubmesh(Mesh baseMesh, int submeshIndex)
        {
            // Function adapted from the MeshCreationHelper.cs script on the Unify Community Wiki

            Mesh newMesh = new Mesh();

            List <int> triangles = new List <int>();

            triangles.AddRange(baseMesh.GetTriangles(submeshIndex)); // the triangles of the sub mesh

            List <Vector3> newVertices = new List <Vector3>();
            List <Vector2> newUvs      = new List <Vector2>();
            List <Vector2> newUv2s     = new List <Vector2>();
            List <Vector2> newUv3s     = new List <Vector2>();
            List <Vector2> newUv4s     = new List <Vector2>();
            List <Vector3> newNormals  = new List <Vector3>();
            List <Color>   newColours  = new List <Color>();
            List <Vector4> newTangents = new List <Vector4>();

            Dictionary <int, int> oldToNewIndices = new Dictionary <int, int>();
            int newIndex = 0;
            int i        = 0;

            // Improve performance by almost 50% by pre-defining variables and only getting the length of an array once.
            int numBaseMeshVerts    = baseMesh.vertices.Length;
            int numBaseMeshColours  = (baseMesh.colors == null ? 0 : baseMesh.colors.Length);
            int numBaseMeshNormals  = (baseMesh.normals == null ? 0 : baseMesh.normals.Length);
            int numBaseMeshTangents = (baseMesh.tangents == null ? 0 : baseMesh.tangents.Length);
            int numBaseMeshuvs      = (baseMesh.uv == null ? 0 : baseMesh.uv.Length);
            int numBaseMeshuv2s     = (baseMesh.uv2 == null ? 0 : baseMesh.uv2.Length);
            int numBaseMeshuv3s     = (baseMesh.uv3 == null ? 0 : baseMesh.uv3.Length);
            int numBaseMeshuv4s     = (baseMesh.uv4 == null ? 0 : baseMesh.uv4.Length);

            // Collect the vertices and uvs
            for (i = 0; i < numBaseMeshVerts; i++)
            {
                if (triangles.Contains(i))
                {
                    newVertices.Add(baseMesh.vertices[i]);

                    if (numBaseMeshColours > i)
                    {
                        newColours.Add(baseMesh.colors[i]);
                    }
                    else
                    {
                        newColours.Add(Color.white);
                    }
                    if (numBaseMeshNormals > i)
                    {
                        newNormals.Add(baseMesh.normals[i]);
                    }
                    if (numBaseMeshTangents > i)
                    {
                        newTangents.Add(baseMesh.tangents[i]);
                    }

                    if (numBaseMeshuvs > i)
                    {
                        newUvs.Add(baseMesh.uv[i]);
                    }
                    if (numBaseMeshuv2s > i)
                    {
                        newUv2s.Add(baseMesh.uv2[i]);
                    }
                    if (numBaseMeshuv3s > i)
                    {
                        newUv3s.Add(baseMesh.uv2[i]);
                    }
                    if (numBaseMeshuv4s > i)
                    {
                        newUv4s.Add(baseMesh.uv2[i]);
                    }

                    oldToNewIndices.Add(i, newIndex);
                    ++newIndex;
                }
            }

            int[] newTriangles = new int[triangles.Count];

            int numNewTriangles = (newTriangles == null ? 0 : newTriangles.Length);

            // Collect the new triangles indicies
            for (i = 0; i < numNewTriangles; i++)
            {
                newTriangles[i] = oldToNewIndices[triangles[i]];
            }
            // Assemble the new mesh with the new vertices/uv/triangles.
            newMesh.vertices = newVertices.ToArray();

            newMesh.triangles = newTriangles;

            if (numBaseMeshuvs > 0)
            {
                newMesh.uv = newUvs.ToArray();
            }
            if (numBaseMeshuv2s > 0)
            {
                newMesh.uv2 = newUv2s.ToArray();
            }
            if (numBaseMeshuv3s > 0)
            {
                newMesh.uv3 = newUv3s.ToArray();
            }
            if (numBaseMeshuv4s > 0)
            {
                newMesh.uv4 = newUv4s.ToArray();
            }
            if (newMesh.colors.Length > 0)
            {
                newMesh.colors = newColours.ToArray();
            }
            if (newMesh.normals.Length > 0)
            {
                newMesh.normals = newNormals.ToArray();
            }
            else
            {
                newMesh.RecalculateNormals();
            }
            // If tangents don't exist, recalculate tangents so that normalmaps work on combined meshes
            if (newMesh.tangents.Length > 0)
            {
                newMesh.tangents = newTangents.ToArray();
            }
            else
            {
                #if UNITY_5_6_OR_NEWER
                newMesh.RecalculateTangents();
                #else
                newMesh = LBMeshOperations.CalculateTangents(newMesh);
                #endif
            }

            // Re-calculate bounds for the renderer.
            newMesh.RecalculateBounds();

            return(newMesh);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Update the mesh with the vert, triangle, normal data.
        /// Recalculate Bounds
        /// Recalculate Normals if required
        /// NOTE: MegaSplat uses color.a, uv4.x, uv4.w
        /// Currently doesn't update uvs as vector4s..
        /// </summary>
        /// <param name="flipNormals"></param>
        /// <param name="showErrors"></param>
        /// <returns></returns>
        public bool UpdateMesh(bool flipNormals, bool showErrors)
        {
            bool isSuccess = false;

            // Do some validation
            if (mesh == null)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - mesh cannot be null");
                }
            }
            else if (verts == null)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - verts cannot be null");
                }
            }
            else if (verts.Count > 65000)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - vert count of " + verts.Count + " is greater than 65000");
                }
            }
            else if (normals == null)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - normals cannot be null");
                }
            }
            else if (uvs == null)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - uvs cannot be null");
                }
            }
            else if (triangles == null)
            {
                if (showErrors)
                {
                    Debug.Log("LBMesh.UpdateMesh - triangles cannot be null");
                }
            }
            //else if (colours == null) { if (showErrors) { Debug.Log("LBMesh.UpdateMesh - colours cannot be null"); } }
            else
            {
                mesh.Clear();
                mesh.SetVertices(verts);
                mesh.SetTriangles(triangles, 0, true);

                if (colours != null)
                {
                    if (colours.Count > 0)
                    {
                        // Populate an array with the Vector4 "colour" data from lbMesh.
                        UnityEngine.Color[] colorsArray = new Color[colours.Count];
                        if (colorsArray != null)
                        {
                            for (int c = 0; c < colours.Count; c++)
                            {
                                Vector4 colour = colours[c];
                                // TODO A color has direct conversion to vector4 so probably just setting to vector4 would
                                // be faster. Need to test.
                                colorsArray[c] = new Color(colour.x, colour.y, colour.z, colour.w);
                            }
                            mesh.colors = colorsArray;
                        }
                    }
                }

                // If they exist, apply the UVs
                if (uvs != null && uvs.Count > 0)
                {
                    mesh.SetUVs(0, uvs);
                }
                if (uv2s != null && uv2s.Count > 0)
                {
                    mesh.SetUVs(1, uv2s);
                }
                if (uv3s != null && uv3s.Count > 0)
                {
                    mesh.SetUVs(2, uv3s);
                }
                if (uv4s != null && uv4s.Count > 0)
                {
                    mesh.SetUVs(3, uv4s);
                }

                // uv3,4 can also be Vector4s...
                if (normals != null && normals.Count > 0)
                {
                    mesh.SetNormals(normals);
                }
                else
                {
                    mesh.RecalculateNormals();
                }

                // flip normals on the mesh itself after normals have been either added from LBMesh
                // or by recalculating the normals. Don't update the original LBMesh normals list
                if (flipNormals)
                {
                    LBMeshOperations.FlipNormals(mesh);
                }

                // Recalc gets done with SetTriangles() above
                //mesh.RecalculateBounds();

                if (tangents != null && tangents.Count > 0)
                {
                    mesh.SetTangents(tangents);
                }
                else
                {
                    //mesh = LBMeshOperations.ReCalculateTangents(mesh);
                    mesh = LBMeshOperations.CalculateTangents(mesh);
                }

                isSuccess = true;
            }

            return(isSuccess);
        }