/// <summary>Generate a <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair from the given planes (and optional other values)</summary>
        /// <remarks><note>Keep in mind that the planes encapsulate the geometry we're generating, so it can only be <i>convex</i>.</note></remarks>
        /// <param name="controlMesh">The generated <see cref="RealtimeCSG.Legacy.ControlMesh"/></param>
        /// <param name="shape">The generated <see cref="RealtimeCSG.Legacy.Shape"/></param>
        /// <param name="planes">The geometric planes of all the surfaces that define this convex shape</param>
        /// <param name="tangents">The tangents for each plane (optional)</param>
        /// <param name="binormals">The binormals for each plane (optional)</param>
        /// <param name="materials">The materials for each plane (optional)</param>
        /// <param name="textureMatrices">The texture matrices for each plane (optional)</param>
        /// <param name="textureMatrixSpace">The texture matrix space for each plane (optional)</param>
        /// <param name="smoothingGroups">The smoothing groups for each plane (optional)</param>
        /// <param name="texGenFlags">The <see cref="RealtimeCSG.Legacy.TexGenFlags"/> for each plane (optional)</param>
        /// <returns>*true* on success, *false* on failure</returns>
        public static bool CreateControlMeshFromPlanes(out ControlMesh controlMesh,
                                                       out Shape shape,
                                                       UnityEngine.Plane[]              planes,
                                                       UnityEngine.Vector3[]    tangents        = null,
                                                       UnityEngine.Vector3[]    binormals       = null,
                                                       UnityEngine.Material[]   materials       = null,
                                                       UnityEngine.Matrix4x4[]  textureMatrices = null,
                                                       TextureMatrixSpace textureMatrixSpace    = TextureMatrixSpace.WorldSpace,
                                                       uint[]                                   smoothingGroups = null,
                                                       TexGenFlags[]                    texGenFlags             = null)
        {
            controlMesh = null;
            shape       = null;
            if (planes == null)
            {
                Debug.LogError("The planes array is not allowed to be null");
                return(false);
            }
            if (planes.Length < 4)
            {
                Debug.LogError("The planes array must have at least 4 planes");
                return(false);
            }
            if (materials == null)
            {
                materials = new Material[planes.Length];
                for (int i = 0; i < materials.Length; i++)
                {
                    materials[i] = CSGSettings.DefaultMaterial;
                }
            }
            if (planes.Length != materials.Length ||
                (textureMatrices != null && planes.Length != textureMatrices.Length) ||
                (tangents != null && tangents.Length != textureMatrices.Length) ||
                (binormals != null && binormals.Length != textureMatrices.Length) ||
                (smoothingGroups != null && smoothingGroups.Length != materials.Length))
            {
                Debug.LogError("All non null arrays need to be of equal length");
                return(false);
            }

            shape             = new Shape();
            shape.TexGenFlags = new TexGenFlags[planes.Length];
            shape.Surfaces    = new Surface[planes.Length];
            shape.TexGens     = new TexGen[planes.Length];
            for (int i = 0; i < planes.Length; i++)
            {
                shape.Surfaces[i].Plane = new CSGPlane(planes[i].normal, -planes[i].distance);

                Vector3 tangent, binormal;
                if (tangents != null && binormals != null)
                {
                    tangent  = tangents[i];
                    binormal = binormals[i];
                }
                else
                {
                    GeometryUtility.CalculateTangents(planes[i].normal, out tangent, out binormal);
                }

                shape.Surfaces[i].Tangent     = -tangent;
                shape.Surfaces[i].BiNormal    = -binormal;
                shape.Surfaces[i].TexGenIndex = i;
                shape.TexGens[i] = new TexGen(materials[i]);
                if (smoothingGroups != null)
                {
                    shape.TexGens[i].SmoothingGroup = smoothingGroups[i];
                }
                if (texGenFlags != null)
                {
                    shape.TexGenFlags[i] = texGenFlags[i];
                }
                else
                {
                    shape.TexGenFlags[i] = RealtimeCSG.CSGSettings.DefaultTexGenFlags;
                }
            }

            controlMesh = ControlMeshUtility.CreateFromShape(shape, MathConstants.DistanceEpsilon);
            if (controlMesh == null)
            {
                return(false);
            }

            if (!ControlMeshUtility.Validate(controlMesh, shape))
            {
                //Debug.LogError("Generated mesh is not valid");
                return(false);
            }

            if (textureMatrices != null)
            {
                int n = 0;
                for (var i = 0; i < planes.Length; i++)
                {
                    if (shape.Surfaces[n].TexGenIndex != i)
                    {
                        continue;
                    }
                    shape.Surfaces[n].TexGenIndex = n;
                    SurfaceUtility.AlignTextureSpaces(textureMatrices[i], textureMatrixSpace == TextureMatrixSpace.PlaneSpace, ref shape.TexGens[n], ref shape.TexGenFlags[n], ref shape.Surfaces[n]);
                    n++;
                }
            }
            return(true);
        }
Example #2
0
        public static void Flip(CSGBrush[] brushes, Matrix4x4 flipMatrix, string undoDescription = "Flip brushes")
        {
            var fail = false;

            Undo.IncrementCurrentGroup();
            Undo.RegisterCompleteObjectUndo(brushes.ToArray <UnityEngine.Object>(), undoDescription);

            var isGlobal = Tools.pivotRotation == PivotRotation.Global;

            var centerAll = BoundsUtilities.GetCenter(brushes);

            for (var t = 0; t < brushes.Length; t++)
            {
                var brush    = brushes[t];
                var shape    = brush.Shape;
                var position = brush.transform.position;

                Matrix4x4 brushFlip;
                Vector3   brushCenter;
                if (isGlobal)
                {
                    brushFlip = brush.transform.localToWorldMatrix *
                                flipMatrix *
                                brush.transform.worldToLocalMatrix;
                    brushCenter = brush.transform.InverseTransformPoint(centerAll) - position;
                }
                else
                {
                    brushFlip   = flipMatrix;
                    brushCenter = brush.transform.InverseTransformPoint(centerAll);
                }

                for (var s = 0; s < shape.Surfaces.Length; s++)
                {
                    var plane = shape.Surfaces[s].Plane;

                    var normal   = brushFlip.MultiplyVector(plane.normal);
                    var biNormal = brushFlip.MultiplyVector(shape.Surfaces[s].BiNormal);
                    var tangent  = brushFlip.MultiplyVector(shape.Surfaces[s].Tangent);

                    var pointOnPlane = plane.pointOnPlane;
                    pointOnPlane -= brushCenter;
                    pointOnPlane  = brushFlip.MultiplyPoint(pointOnPlane);
                    pointOnPlane += brushCenter;

                    shape.Surfaces[s].Plane    = new CSGPlane(normal, pointOnPlane);
                    shape.Surfaces[s].BiNormal = biNormal;
                    shape.Surfaces[s].Tangent  = tangent;
                }

                var controlMesh = brush.ControlMesh;
                brush.Shape = shape;

                brush.ControlMesh = ControlMeshUtility.CreateFromShape(shape);
                if (brush.ControlMesh == null)
                {
                    brush.ControlMesh = controlMesh;
                    fail = true;
                    break;
                }

                ShapeUtility.CreateCutter(shape, brush.ControlMesh);
                brush.EnsureInitialized();

                brush.ControlMesh.SetDirty();
                EditorUtility.SetDirty(brush);

                InternalCSGModelManager.CheckSurfaceModifications(brush, true);

                ControlMeshUtility.RebuildShape(brush);
            }
            if (fail)
            {
                Debug.Log("Failed to perform operation");
                Undo.RevertAllInCurrentGroup();
            }
            InternalCSGModelManager.Refresh();
        }