Beispiel #1
0
        public void Mesh_CreateIntersectionBoxBrush_RetrieveMesh_RetrievedMeshIsEmpty()
        {
            var tree = CSGTree.Create(
                CreateBoxBrush(operation: CSGOperationType.Intersecting)
                );

            GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, simpleMeshTypes, expectEmpty: true);

            Assert.Null(generatedMesh);
        }
Beispiel #2
0
        public void Mesh_CreateAdditiveBoxBrush_RetrieveMesh_RetrievedMeshIsACube()
        {
            var tree = CSGTree.Create(
                CreateBoxBrush(operation: CSGOperationType.Additive)
                );

            GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, simpleMeshTypes, expectEmpty: false);

            ValidateIsCorrectBox(generatedMesh);
        }
    public void Mesh_CreateSubtractiveCubeBrush_RetrieveMesh_RetrievedMeshIsEmpty()
    {
        var tree = CSGTree.Create(
            CreateCubeBrush(operation: CSGOperationType.Subtractive)
            );

        GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, simpleMeshTypes, expectEmpty: true);

        Assert.Null(generatedMesh);
    }
Beispiel #4
0
        public void Mesh_LargeAdditiveBoxBrushWithIntersectingBoxBrush_RetrievedMeshHasIntersectingBoxMaterial()
        {
            var tree = CSGTree.Create(
                CreateBoxBrush(operation: CSGOperationType.Additive, material: material2, size: Vector3.one * 2),
                CreateBoxBrush(operation: CSGOperationType.Intersecting, material: material1)
                );

            GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, materialMeshTypes, expectEmpty: false);

            ValidateIsCorrectBox(generatedMesh);
            Assert.AreEqual(materialID1, generatedMesh.description.surfaceParameter);
        }
Beispiel #5
0
        public void Mesh_SubtractiveBoxBrushWithAdditiveBoxBrush_RetrievedMeshIsBox()
        {
            var tree = CSGTree.Create(
                CreateBoxBrush(operation: CSGOperationType.Subtractive, material: material2),
                CreateBoxBrush(operation: CSGOperationType.Additive, material: material1)
                );

            GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, materialMeshTypes, expectEmpty: false);

            ValidateIsCorrectBox(generatedMesh);
            Assert.AreEqual(materialID1, generatedMesh.description.surfaceParameter);
        }
    public void Mesh_AdditiveCubeBrushOverlapsWithIntersectingCubeBrush_RetrievedMeshHasIntersectingCubeMaterial()
    {
        var tree = CSGTree.Create(
            CreateCubeBrush(operation: CSGOperationType.Additive, material: material2),
            CreateCubeBrush(operation: CSGOperationType.Intersecting, material: material1)
            );

        GeneratedMeshContents generatedMesh = GeneratedMeshAndValidate(tree, materialMeshTypes, expectEmpty: false);

        ValidateIsCorrectCube(generatedMesh);
        Assert.AreEqual(materialID2, generatedMesh.description.surfaceParameter);
    }
Beispiel #7
0
        static void ValidateIsCorrectBox(GeneratedMeshContents generatedMesh)
        {
            Assert.NotNull(generatedMesh.indices);
            Assert.NotNull(generatedMesh.positions);
            Assert.AreEqual(boxIndexCount, generatedMesh.indices.Length);      // 6 sides, 2 triangles per side, 3 indices per triangle
            Assert.AreEqual(boxVertexCount, generatedMesh.positions.Length);   // 6 sides, 4 vertices per side

            var vertexChannels = generatedMesh.description.meshQuery.UsedVertexChannels;

            //		if ((vertexChannels & VertexChannelFlags.Color) == VertexChannelFlags.Color)
            //		{
            //			Assert.NotNull(generatedMesh.colors);
            //			Assert.AreEqual(generatedMesh.positions.Length, generatedMesh.colors.Length);
            //		} else
            //			Assert.Null(generatedMesh.colors);

            if ((vertexChannels & VertexChannelFlags.Tangent) == VertexChannelFlags.Tangent)
            {
                Assert.NotNull(generatedMesh.tangents);
                Assert.AreEqual(generatedMesh.positions.Length, generatedMesh.tangents.Length);
            }
            else
            {
                Assert.Null(generatedMesh.tangents);
            }

            if ((vertexChannels & VertexChannelFlags.Normal) == VertexChannelFlags.Normal)
            {
                Assert.NotNull(generatedMesh.normals);
                Assert.AreEqual(generatedMesh.positions.Length, generatedMesh.normals.Length);
            }
            else
            {
                Assert.Null(generatedMesh.normals);
            }

            if ((vertexChannels & VertexChannelFlags.UV0) == VertexChannelFlags.UV0)
            {
                Assert.NotNull(generatedMesh.uv0);
                Assert.AreEqual(generatedMesh.positions.Length, generatedMesh.uv0.Length);
            }
            else
            {
                Assert.Null(generatedMesh.uv0);
            }
        }
Beispiel #8
0
        static GeneratedMeshContents GeneratedMeshAndValidate(CSGTree tree, MeshQuery[] meshTypes, bool expectEmpty = false)
        {
            GeneratedMeshContents generatedMesh = null;

            GeneratedMeshDescription[] meshDescriptions = null;
            bool treeWasDirtyBefore = false;
            bool treeIsDirtyAfter   = true;

            tree.SetDirty();
            bool haveChanges = CSGManager.Flush(); // Note: optional

            if (haveChanges)
            {
                treeWasDirtyBefore = tree.Dirty; // Note: optional
                if (treeWasDirtyBefore)
                {
                    meshDescriptions = tree.GetMeshDescriptions(meshTypes);
                    if (meshDescriptions != null)
                    {
                        var meshDescription = meshDescriptions[0];
                        generatedMesh = tree.GetGeneratedMesh(meshDescription);
                    }
                    treeIsDirtyAfter = tree.Dirty;
                }
            }

            Assert.IsTrue(haveChanges);
            Assert.IsTrue(treeWasDirtyBefore);
            Assert.IsFalse(treeIsDirtyAfter);
            if (expectEmpty)
            {
                Assert.Null(meshDescriptions);
                Assert.Null(generatedMesh);
            }
            else
            {
                Assert.NotNull(meshDescriptions);
                Assert.NotNull(generatedMesh);
                Assert.AreEqual(meshDescriptions[0].meshQuery, meshTypes[0]);
                Assert.AreEqual(simpleMeshTypes.Length, meshDescriptions.Length);
                Assert.IsTrue(generatedMesh.description.vertexCount > 0 &&
                              generatedMesh.description.indexCount > 0);
            }
            return(generatedMesh);
        }
        public static bool UpdateMesh(string baseName,
                                      GeneratedMeshContents generatedMesh,
                                      GeneratedMeshDescription inputMeshDescription,
                                      RenderSurfaceType renderSurfaceType,
                                      ref bool outputHasGeneratedNormals,
                                      ref Mesh sharedMesh,
                                      bool editorOnly)
        {
            var startUpdateMeshTime = EditorApplication.timeSinceStartup;

            {
                MeshInstanceManager.ClearOrCreateMesh(baseName, editorOnly, ref outputHasGeneratedNormals, ref sharedMesh);

                // finally, we start filling our (sub)meshes using the C# arrays
                sharedMesh.vertices = generatedMesh.positions;
                if (generatedMesh.normals != null)
                {
                    sharedMesh.normals = generatedMesh.normals;
                }
                if (generatedMesh.tangents != null)
                {
                    sharedMesh.tangents = generatedMesh.tangents;
                }
//				if (generatedMesh.colors   != null) sharedMesh.colors	= generatedMesh.colors;
                if (generatedMesh.uv0 != null)
                {
                    sharedMesh.uv = generatedMesh.uv0;
                }

                // fill the mesh with the given indices
                sharedMesh.SetTriangles(generatedMesh.indices, 0, calculateBounds: true);
                //sharedMesh.RecalculateBounds();
                //sharedMesh.bounds = generatedMesh.bounds; // why doesn't this work?
            }
            updateMeshTime += EditorApplication.timeSinceStartup - startUpdateMeshTime;

            if (renderSurfaceType != RenderSurfaceType.Normal)
            {
                outputHasGeneratedNormals = ((inputMeshDescription.meshQuery.UsedVertexChannels & VertexChannelFlags.Normal) != 0);
            }
            return(true);
        }
Beispiel #10
0
        private static bool UpdateMesh(CSGModel model,
                                       GeneratedMeshDescription meshDescription,
                                       RenderSurfaceType renderSurfaceType,
                                       ref GeneratedMeshContents outputGeneratedMeshContents,
                                       ref bool outputHasGeneratedNormals,
                                       ref Mesh sharedMesh)
        {
            // create our arrays on the C# side with the correct size
            GeneratedMeshContents generatedMesh;
            var startGetModelMeshesTime = EditorApplication.timeSinceStartup;

            {
                generatedMesh = External.GetModelMesh(model.modelNodeID, meshDescription);
                if (generatedMesh == null)
                {
                    return(false);
                }
            }
            getModelMeshesTime += EditorApplication.timeSinceStartup - startGetModelMeshesTime;

            UpdateMesh(generatedMesh,
                       meshDescription,
                       renderSurfaceType,
                       ref outputHasGeneratedNormals,
                       ref sharedMesh);

            /*
             #if UNITY_2018_3_OR_NEWER
             * var modelGameObject = model.gameObject;
             * var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(modelGameObject);
             * if (prefabStage != null && string.IsNullOrEmpty(AssetDatabase.GetAssetPath(sharedMesh)))
             * {
             *      var prefabAssetPath = prefabStage.prefabAssetPath;
             *      if (!string.IsNullOrEmpty(prefabAssetPath))
             *              AssetDatabase.AddObjectToAsset(sharedMesh, prefabAssetPath);
             *      UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(modelGameObject.scene);
             * }
             #endif
             */
            outputGeneratedMeshContents = generatedMesh;
            return(true);
        }
Beispiel #11
0
    public void GenerateMesh()
    {
        // The mesh queries define how meshes are generated using the BrushMesh surface layer information
        MeshQuery[] meshQueries = GetMeshQueries();


        // Create a tree
        // Note: this can be cached and updated separately.
        CSGTree tree = CreateTree();


        // At this point, when you have a tree that you update frequently, you can also potentially check if it's Dirty or not.
        // If it is, it means it has been modified since the last time tree.GetMeshDescriptions has been called.


        // Find all the potential meshes that could be generated with our queries.
        // There is no guarantee that these meshes will exist. It might also be split into multiple meshes when it's too large
        GeneratedMeshDescription[] meshDescriptions = tree.GetMeshDescriptions(meshQueries, VertexChannelFlags.All);

        if (meshDescriptions != null)
        {
            // Iterate through all the meshes that we've found
            foreach (var meshDescription in meshDescriptions)
            {
                // At this point, it's possible to check the Hash values stored in meshDescription,
                // to check if this particular type of mesh has already been generated before (perhaps in a previous iteration)
                // You could then potentially early out and avoid retrieving the generated mesh and converting it into a new UnityEngine.Mesh.

                // Actually generate the mesh on the native side, potentially generate smooth normals etc. and retrieve the mesh.
                GeneratedMeshContents contents = tree.GetGeneratedMesh(meshDescription);

                // Note: It's possible to re-use this UnityEngine.Mesh
                UnityEngine.Mesh unityMesh = new UnityEngine.Mesh();

                // Copy the generated mesh to the UnityEngine.Mesh
                contents.CopyTo(unityMesh);

                // ... assign it to a MeshRenderer/MeshCollider etc.
            }
        }
    }