示例#1
0
    public BrushMeshInstance CreateCube(int userID)
    {
        BrushMesh         cube             = RealtimeCSG.Legacy.BrushFactory.CreateCube(Vector3.one);
        BrushMeshInstance cubeMeshInstance = BrushMeshInstance.Create(cube, userID);

        return(cubeMeshInstance);
    }
示例#2
0
        public void CreateBrushMeshInstanceFromBrushMesh()
        {
            BrushMesh brushMesh = TestUtility.CreateBox(Vector3.one, null);

            BrushMeshInstance coreBrushMesh = BrushMeshInstance.Create(brushMesh);

            Assert.AreEqual(true, coreBrushMesh.Valid);
        }
 public void Clear()
 {
     if (brushMesh == null)
     {
         brushMesh = new BrushMesh();
     }
     polygons = null;
 }
示例#4
0
        public void DestroyBrushMeshInstance()
        {
            BrushMesh         brushMesh         = TestUtility.CreateBox(Vector3.one, null);
            BrushMeshInstance brushMeshInstance = BrushMeshInstance.Create(brushMesh);

            brushMeshInstance.Destroy();

            Assert.AreEqual(false, brushMeshInstance.Valid);
        }
        internal BrushMesh CreateOrUpdateBrushMesh()
        {
            if (brushMesh == null)
            {
                brushMesh = new BrushMesh();
            }

            // In case a user sets "polygons" to null, for consistency
            if (polygons == null ||
                polygons.Length == 0)
            {
                brushMesh.polygons = null;
                return(brushMesh);
            }

            if (brushMesh.polygons == null ||
                brushMesh.polygons.Length != polygons.Length)
            {
                brushMesh.polygons = new BrushMesh.Polygon[polygons.Length];
            }

            var dstPolygons = brushMesh.polygons;

            for (int i = 0; i < polygons.Length; i++)
            {
                if (polygons[i] == null)
                {
                    Debug.LogError("Polygons[" + i + "] is not initialized.");
                    Clear();
                    return(brushMesh);
                }
                dstPolygons[i].firstEdge   = polygons[i].firstEdge;
                dstPolygons[i].edgeCount   = polygons[i].edgeCount;
                dstPolygons[i].surfaceID   = polygons[i].surfaceID;
                dstPolygons[i].description = polygons[i].description;

                var surfaceAsset = polygons[i].surfaceAsset;
                if (surfaceAsset == null)
                {
                    dstPolygons[i].layers.layerUsage      = LayerUsageFlags.None;
                    dstPolygons[i].layers.layerParameter1 = 0;
                    dstPolygons[i].layers.layerParameter2 = 0;
                    continue;
                }
                dstPolygons[i].layers.layerUsage      = surfaceAsset.LayerUsage;
                dstPolygons[i].layers.layerParameter1 = surfaceAsset.RenderMaterialInstanceID;
                dstPolygons[i].layers.layerParameter2 = surfaceAsset.PhysicsMaterialInstanceID;
            }

            if (!Validate())
            {
                Clear();
            }

            return(brushMesh);
        }
示例#6
0
        static BrushMeshInstance CreateBox(Vector3 size, CSGOperationType operation = CSGOperationType.Additive, Material material = null)
        {
            if (material == null)
            {
                material = material2;
            }
            var       brushMaterial = ChiselBrushMaterial.CreateInstance(material);
            BrushMesh brushMesh     = TestUtility.CreateBox(size, brushMaterial);

            return(BrushMeshInstance.Create(brushMesh));
        }
示例#7
0
        public void CreateBrushMesh()
        {
            BrushMesh brushMesh = TestUtility.CreateBox(Vector3.one, null);

            Assert.AreNotEqual(null, brushMesh);
            Assert.AreNotEqual(null, brushMesh.vertices);
            Assert.AreNotEqual(null, brushMesh.halfEdges);
            Assert.AreNotEqual(null, brushMesh.polygons);
            Assert.AreEqual(8, brushMesh.vertices.Length);
            Assert.AreEqual(24, brushMesh.halfEdges.Length);
            Assert.AreEqual(6, brushMesh.polygons.Length);
        }
示例#8
0
        public void CreateBrushMeshInstanceFromBrushMesh()
        {
            var layers = new SurfaceLayers
            {
                layerUsage = LayerUsageFlags.None
            };
            BrushMesh brushMesh = TestUtility.CreateBox(Vector3.one, layers);

            BrushMeshInstance coreBrushMesh = BrushMeshInstance.Create(brushMesh);

            Assert.AreEqual(true, coreBrushMesh.Valid);
        }
    public void CreateCoreBrushMeshFromControlMesh()
    {
        ControlMesh controlMesh;
        Shape       shape;

        BrushFactory.CreateCubeControlMesh(out controlMesh, out shape, Vector3.one);
        BrushMesh brushMesh = RealtimeCSG.Legacy.BrushFactory.GenerateFromControlMesh(controlMesh, shape);

        BrushMeshInstance coreBrushMesh = BrushMeshInstance.Create(brushMesh);

        Assert.AreEqual(true, coreBrushMesh.Valid);
    }
示例#10
0
        public void DestroyBrushMeshInstance()
        {
            var layers = new SurfaceLayers
            {
                layerUsage = LayerUsageFlags.None
            };
            BrushMesh         brushMesh         = TestUtility.CreateBox(Vector3.one, layers);
            BrushMeshInstance brushMeshInstance = BrushMeshInstance.Create(brushMesh);

            brushMeshInstance.Destroy();

            Assert.AreEqual(false, brushMeshInstance.Valid);
        }
    static BrushMeshInstance CreateCube(Vector3 size, CSGOperationType operation = CSGOperationType.Additive, Material material = null)
    {
        if (material == null)
        {
            material = material2;
        }
        ControlMesh controlMesh;
        Shape       shape;

        BrushFactory.CreateCubeControlMesh(out controlMesh, out shape, size, material);
        BrushMesh brushMesh = RealtimeCSG.Legacy.BrushFactory.GenerateFromControlMesh(controlMesh, shape);

        return(BrushMeshInstance.Create(brushMesh));
    }
        static BrushMeshInstance CreateBox(Vector3 size, CSGOperationType operation = CSGOperationType.Additive, Material material = null)
        {
            if (material == null)
            {
                material = material2;
            }
            var layers = new SurfaceLayers
            {
                layerUsage      = LayerUsageFlags.All,
                layerParameter1 = (material) ? material.GetInstanceID() : 0
            };
            BrushMesh brushMesh = TestUtility.CreateBox(size, layers);

            return(BrushMeshInstance.Create(brushMesh));
        }
示例#13
0
        public void CreateBrushMesh()
        {
            var layers = new SurfaceLayers
            {
                layerUsage = LayerUsageFlags.None
            };
            BrushMesh brushMesh = TestUtility.CreateBox(Vector3.one, layers);

            Assert.AreNotEqual(null, brushMesh);
            Assert.AreNotEqual(null, brushMesh.vertices);
            Assert.AreNotEqual(null, brushMesh.halfEdges);
            Assert.AreNotEqual(null, brushMesh.polygons);
            Assert.AreEqual(8, brushMesh.vertices.Length);
            Assert.AreEqual(24, brushMesh.halfEdges.Length);
            Assert.AreEqual(6, brushMesh.polygons.Length);
        }
    public void CreateBrushMeshFromControlMesh()
    {
        ControlMesh controlMesh;
        Shape       shape;

        BrushFactory.CreateCubeControlMesh(out controlMesh, out shape, Vector3.one);

        BrushMesh brushMesh = RealtimeCSG.Legacy.BrushFactory.GenerateFromControlMesh(controlMesh, shape);

        Assert.AreNotEqual(null, brushMesh);
        Assert.AreNotEqual(null, brushMesh.vertices);
        Assert.AreNotEqual(null, brushMesh.halfEdges);
        Assert.AreNotEqual(null, brushMesh.polygons);
        Assert.AreEqual(8, brushMesh.vertices.Length);
        Assert.AreEqual(24, brushMesh.halfEdges.Length);
        Assert.AreEqual(6, brushMesh.polygons.Length);
    }
示例#15
0
        // Creates a new optimized/fixed brushMesh based on the brushMesh inside of the generator
        // this will not be copied to the generator until the current operation is complete.
        // This prevents, for example, dragging an edge over another edge DURING a dragging operation messing things up.
        void UpdateEditableOutline(ChiselBrush generator, float3[] vertices)
        {
            generatorModified = true;
            var outline = activeOutlines[generator];

            var internalBrushMesh = new BrushMesh(outline.brushMesh);

            // Removes infinitely thin polygons (for instance, when snapping edges to edges)
            internalBrushMesh.RemoveDegenerateTopology(out outline.edgeRemap, out outline.polygonRemap);

            internalBrushMesh.CalculatePlanes();

            // If the brush is concave, we set the generator to not be valid, so that when we commit, it will be reverted
            generator.definition.ValidState = !internalBrushMesh.IsConcave() && // TODO: eventually allow concave shapes
                                              !internalBrushMesh.IsSelfIntersecting() &&
                                              internalBrushMesh.HasVolume();

            generator.definition.brushOutline = internalBrushMesh;

            generator.OnValidate();

            outline.Rebuild();
        }
示例#16
0
        // Creates a new optimized/fixed brushMesh based on the brushMesh inside of the generator
        // this will not be copied to the generator until the current operation is complete.
        // This prevents, for example, dragging an edge over another edge DURING a dragging operation messing things up.
        void UpdateEditableOutline(ChiselBrushComponent generator)
        {
            generatorModified = true;
            var outline = activeOutlines[generator];

            var internalBrushMesh = new BrushMesh(outline.brushMesh);

            // Removes infinitely thin polygons (for instance, when snapping edges to edges)
            internalBrushMesh.RemoveDegenerateTopology(out outline.edgeRemap, out outline.polygonRemap);

            internalBrushMesh.CalculatePlanes();

            // If the brush is concave, we set the generator to not be valid, so that when we commit, it will be reverted
            generator.definition.ValidState = internalBrushMesh.HasVolume() &&          // TODO: implement this, so we know if a brush is a 0D/1D/2D shape
                                              !internalBrushMesh.IsConcave() &&         // TODO: eventually allow concave shapes
                                              !internalBrushMesh.IsSelfIntersecting();  // TODO: in which case this needs to be implemented

            generator.definition.brushOutline = internalBrushMesh;

            generator.definition.EnsurePlanarPolygons();
            generator.OnValidate();

            outline.Rebuild();
        }
示例#17
0
        /// <summary>
        /// Imports the specified world into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="world">The world to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(Transform rootTransform, MapWorld world)
        {
            _conversionScale = 1.0f / _Scale;

            // create a material searcher to associate materials automatically.
            MaterialSearcher materialSearcher = new MaterialSearcher();

            var mapTransform = CreateGameObjectWithUniqueName(world.mapName, rootTransform);

            mapTransform.position = Vector3.zero;

            // Index of entities by trenchbroom id
            var entitiesById = new Dictionary <int, EntityContainer>();

            var layers = new List <EntityContainer>();

            for (int e = 0; e < world.Entities.Count; e++)
            {
                var entity = world.Entities[e];

                //EntityContainer eContainer = null;

                if (entity.tbId >= 0)
                {
                    var name       = String.IsNullOrEmpty(entity.tbName) ? "Unnamed" : entity.tbName;
                    var t          = CreateGameObjectWithUniqueName(name, mapTransform);
                    var eContainer = new EntityContainer(t, entity);
                    entitiesById.Add(entity.tbId, eContainer);

                    if (entity.tbType == "_tb_layer")
                    {
                        layers.Add(eContainer);
                        eContainer.transform.SetParent(null); // unparent until layers are sorted by sort index
                    }
                }
            }

            var defaultLayer = CreateGameObjectWithUniqueName("Default Layer", mapTransform);

            layers = layers.OrderBy(l => l.entity.tbLayerSortIndex).ToList(); // sort layers by layer sort index

            foreach (var l in layers)
            {
                l.transform.SetParent(mapTransform); // parent layers to map in order
            }

            bool valveFormat = world.valveFormat;

            // iterate through all entities.
            for (int e = 0; e < world.Entities.Count; e++)
            {
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("Importing Quake 1 Map", "Converting Quake 1 Entities To Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count);
#endif
                MapEntity entity = world.Entities[e];

                Transform brushParent = mapTransform;

                bool isLayer   = false;
                bool isTrigger = false;

                if (entity.ClassName == "worldspawn")
                {
                    brushParent = defaultLayer;
                }
                else if (entity.tbType == "_tb_layer")
                {
                    isLayer = true;
                    if (entitiesById.TryGetValue(entity.tbId, out EntityContainer eContainer))
                    {
                        brushParent = eContainer.transform;
                    }
                }
                else if (entity.tbType == "_tb_group")
                {
                    if (entitiesById.TryGetValue(entity.tbId, out EntityContainer eContainer))
                    {
                        brushParent = eContainer.transform;
                    }
                }
                else
                {
                    if (entity.ClassName.Contains("trigger"))
                    {
                        isTrigger = true;
                    }

                    brushParent = CreateGameObjectWithUniqueName(entity.ClassName, mapTransform);
                }

                if (brushParent != mapTransform && brushParent != defaultLayer)
                {
                    if (entity.tbGroup > 0)
                    {
                        if (entitiesById.TryGetValue(entity.tbGroup, out EntityContainer eContainer))
                        {
                            brushParent.SetParent(eContainer.transform);
                        }
                    }
                    else if (entity.tbLayer > 0)
                    {
                        if (entitiesById.TryGetValue(entity.tbLayer, out EntityContainer eContainer))
                        {
                            brushParent.SetParent(eContainer.transform);
                        }
                    }
                    else if (!isLayer)
                    {
                        brushParent.SetParent(defaultLayer);
                    }
                }

                //if(entity.)

                if (entity.Brushes.Count == 0)
                {
                    continue;
                }

                var model = ChiselModelManager.CreateNewModel(brushParent);
                // var model = OperationsUtility.CreateModelInstanceInScene(brushParent);
                var parent = model.transform;

                if (isTrigger)
                {
                    //model.Settings = (model.Settings | ModelSettingsFlags.IsTrigger | ModelSettingsFlags.SetColliderConvex | ModelSettingsFlags.DoNotRender);
                }

                // iterate through all entity brushes.
                for (int i = 0; i < entity.Brushes.Count; i++)
                {
                    MapBrush brush = entity.Brushes[i];


                    // build a very large cube brush.
                    ChiselBrush go = ChiselComponentFactory.Create <ChiselBrush>(model);
                    go.definition.surfaceDefinition = new ChiselSurfaceDefinition();
                    go.definition.surfaceDefinition.EnsureSize(6);
                    BrushMesh brushMesh = new BrushMesh();
                    go.definition.brushOutline = brushMesh;
                    BrushMeshFactory.CreateBox(ref brushMesh, new Vector3(-4096, -4096, -4096), new Vector3(4096, 4096, 4096), in go.definition.surfaceDefinition);

                    // prepare for uv calculations of clip planes after cutting.
                    var planes        = new float4[brush.Sides.Count];
                    var planeSurfaces = new ChiselSurface[brush.Sides.Count];

                    // compute all the sides of the brush that will be clipped.
                    for (int j = brush.Sides.Count; j-- > 0;)
                    {
                        MapBrushSide side = brush.Sides[j];

                        // detect excluded polygons.
                        //if (IsExcludedMaterial(side.Material))
                        //polygon.UserExcludeFromFinal = true;
                        // detect collision-only brushes.
                        //if (IsInvisibleMaterial(side.Material))
                        //pr.IsVisible = false;

                        // find the material in the unity project automatically.
                        Material material;

                        string materialName = side.Material.Replace("*", "#");
                        material = materialSearcher.FindMaterial(new string[] { materialName });
                        if (material == null)
                        {
                            material = ChiselMaterialManager.DefaultFloorMaterial;
                        }

                        // create chisel surface for the clip.
                        ChiselSurface surface = new ChiselSurface();
                        surface.brushMaterial      = ChiselBrushMaterial.CreateInstance(material, ChiselMaterialManager.DefaultPhysicsMaterial);
                        surface.surfaceDescription = SurfaceDescription.Default;

                        // detect collision-only polygons.
                        if (IsInvisibleMaterial(side.Material))
                        {
                            surface.brushMaterial.LayerUsage &= ~LayerUsageFlags.RenderReceiveCastShadows;
                        }
                        // detect excluded polygons.
                        if (IsExcludedMaterial(side.Material))
                        {
                            surface.brushMaterial.LayerUsage &= LayerUsageFlags.CastShadows;
                            surface.brushMaterial.LayerUsage |= LayerUsageFlags.Collidable;
                        }

                        // calculate the clipping planes.
                        Plane clip = new Plane(go.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * _conversionScale), go.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * _conversionScale), go.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * _conversionScale));
                        planes[j]        = new float4(clip.normal, clip.distance);
                        planeSurfaces[j] = surface;
                    }

                    // cut all the clipping planes out of the brush in one go.
                    brushMesh.Cut(planes, planeSurfaces);

                    // now iterate over the planes to calculate UV coordinates.
                    int[] indices = new int[brush.Sides.Count];
                    for (int k = 0; k < planes.Length; k++)
                    {
                        var   plane           = planes[k];
                        int   closestIndex    = 0;
                        float closestDistance = math.lengthsq(plane - brushMesh.planes[0]);
                        for (int j = 1; j < brushMesh.planes.Length; j++)
                        {
                            float testDistance = math.lengthsq(plane - brushMesh.planes[j]);
                            if (testDistance < closestDistance)
                            {
                                closestIndex    = j;
                                closestDistance = testDistance;
                            }
                        }
                        indices[k] = closestIndex;
                    }

                    for (int j = 0; j < indices.Length; j++)
                    {
                        brushMesh.planes[indices[j]] = planes[j];
                    }

                    for (int j = brush.Sides.Count; j-- > 0;)
                    {
                        MapBrushSide side = brush.Sides[j];

                        var surface  = brushMesh.polygons[indices[j]].surface;
                        var material = surface.brushMaterial.RenderMaterial;

                        // calculate the texture coordinates.
                        int w = 256;
                        int h = 256;
                        if (material.mainTexture != null)
                        {
                            w = material.mainTexture.width;
                            h = material.mainTexture.height;
                        }
                        var clip = new Plane(planes[j].xyz, planes[j].w);

                        if (world.valveFormat)
                        {
                            var uAxis = new VmfAxis(side.t1, side.Offset.X, side.Scale.X);
                            var vAxis = new VmfAxis(side.t2, side.Offset.Y, side.Scale.Y);
                            CalculateTextureCoordinates(go, surface, clip, w, h, uAxis, vAxis);
                        }
                        else
                        {
                            if (GetTextureAxises(clip, out MapVector3 t1, out MapVector3 t2))
                            {
                                var uAxis = new VmfAxis(t1, side.Offset.X, side.Scale.X);
                                var vAxis = new VmfAxis(t2, side.Offset.Y, side.Scale.Y);
                                CalculateTextureCoordinates(go, surface, clip, w, h, uAxis, vAxis);
                            }
                        }
                    }

                    try
                    {
                        // finalize the brush by snapping planes and centering the pivot point.
                        go.transform.position += brushMesh.CenterAndSnapPlanes();
                    }
                    catch
                    {
                        // Brush failed, destroy brush
                        GameObject.DestroyImmediate(go);
                    }
                }
            }

#if UNITY_EDITOR
            UnityEditor.EditorUtility.ClearProgressBar();
#endif
        }
示例#18
0
        public static void CreateBox(Vector3 size, ChiselBrushMaterial brushMaterial, out BrushMesh box)
        {
            var chiselSurface = new ChiselSurface();

            chiselSurface.brushMaterial = brushMaterial;
            BrushMeshFactory.CreateBox(Vector3.one, in chiselSurface, out box);
        }
        /// <summary>
        /// Imports the specified world into the Chisel model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="world">The world to be imported.</param>
        public static void Import(ChiselModel model, VmfWorld world)
        {
            // create a material searcher to associate materials automatically.
            MaterialSearcher materialSearcher         = new MaterialSearcher();
            HashSet <string> materialSearcherWarnings = new HashSet <string>();

            // iterate through all world solids.
            for (int i = 0; i < world.Solids.Count; i++)
            {
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("Chisel: Importing Source Engine Map (1/3)", "Converting Hammer Solids To Chisel Brushes (" + (i + 1) + " / " + world.Solids.Count + ")...", i / (float)world.Solids.Count);
#endif
                VmfSolid solid = world.Solids[i];

                // don't add triggers to the scene.
                if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                {
                    continue;
                }

                // HACK: Fix me in the future!
                // HACK: Chisel doesn't support collision brushes yet- skip them completely!
                if (solid.Sides.Count > 0 && IsInvisibleMaterial(solid.Sides[0].Material))
                {
                    continue;
                }
                // HACK: Fix me in the future!

                // build a very large cube brush.
                ChiselBrush go = ChiselComponentFactory.Create <ChiselBrush>(model);
                go.definition.surfaceDefinition = new ChiselSurfaceDefinition();
                go.definition.surfaceDefinition.EnsureSize(6);
                BrushMesh brushMesh = new BrushMesh();
                go.definition.brushOutline = brushMesh;
                BrushMeshFactory.CreateBox(ref brushMesh, new Vector3(-4096, -4096, -4096), new Vector3(4096, 4096, 4096), in go.definition.surfaceDefinition);

                // prepare for any displacements.
                List <DisplacementSide> DisplacementSurfaces = new List <DisplacementSide>();

                // prepare for uv calculations of clip planes after cutting.
                var planes        = new float4[solid.Sides.Count];
                var planeSurfaces = new ChiselSurface[solid.Sides.Count];

                // compute all the sides of the brush that will be clipped.
                for (int j = solid.Sides.Count; j-- > 0;)
                {
                    VmfSolidSide side = solid.Sides[j];

                    // detect excluded polygons.
                    //if (IsExcludedMaterial(side.Material))
                    //polygon.UserExcludeFromFinal = true;
                    // detect collision-only brushes.
                    //if (IsInvisibleMaterial(side.Material))
                    //pr.IsVisible = false;

                    // find the material in the unity project automatically.
                    Material material;

                    // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'.
                    string materialName = side.Material.Replace("/", ".");
                    if (materialName.Contains("."))
                    {
                        // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'.
                        string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1);
                        material = materialSearcher.FindMaterial(new string[] { materialName, tiny });
                        if (material == null && materialSearcherWarnings.Add(materialName))
                        {
                            Debug.Log("Chisel: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project.");
                        }
                    }
                    else
                    {
                        // only try finding 'BRICKWALL052D'.
                        material = materialSearcher.FindMaterial(new string[] { materialName });
                        if (material == null && materialSearcherWarnings.Add(materialName))
                        {
                            Debug.Log("Chisel: Tried to find material '" + materialName + "' but it couldn't be found in the project.");
                        }
                    }

                    // fallback to default material.
                    if (material == null)
                    {
                        material = ChiselMaterialManager.DefaultFloorMaterial;
                    }

                    // create chisel surface for the clip.
                    ChiselSurface surface = new ChiselSurface();
                    surface.brushMaterial      = ChiselBrushMaterial.CreateInstance(material, ChiselMaterialManager.DefaultPhysicsMaterial);
                    surface.surfaceDescription = SurfaceDescription.Default;

                    // detect collision-only polygons.
                    if (IsInvisibleMaterial(side.Material))
                    {
                        surface.brushMaterial.LayerUsage &= ~LayerUsageFlags.RenderReceiveCastShadows;
                    }
                    // detect excluded polygons.
                    if (IsExcludedMaterial(side.Material))
                    {
                        surface.brushMaterial.LayerUsage &= LayerUsageFlags.CastShadows;
                        surface.brushMaterial.LayerUsage |= LayerUsageFlags.Collidable;
                    }

                    // calculate the clipping planes.
                    Plane clip = new Plane(go.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                    planes[j]        = new float4(clip.normal, clip.distance);
                    planeSurfaces[j] = surface;

                    // check whether this surface is a displacement.
                    if (side.Displacement != null)
                    {
                        // disable the brush.
                        go.gameObject.GetComponent <ChiselBrush>().enabled = false;

                        // keep track of the surface used to cut the mesh.
                        DisplacementSurfaces.Add(new DisplacementSide {
                            side = side, surface = surface
                        });
                    }
                }

                // cut all the clipping planes out of the brush in one go.
                brushMesh.Cut(planes, planeSurfaces);

                // now iterate over the planes to calculate UV coordinates.
                int[] indices = new int[solid.Sides.Count];
                for (int k = 0; k < planes.Length; k++)
                {
                    var   plane           = planes[k];
                    int   closestIndex    = 0;
                    float closestDistance = math.lengthsq(plane - brushMesh.planes[0]);
                    for (int j = 1; j < brushMesh.planes.Length; j++)
                    {
                        float testDistance = math.lengthsq(plane - brushMesh.planes[j]);
                        if (testDistance < closestDistance)
                        {
                            closestIndex    = j;
                            closestDistance = testDistance;
                        }
                    }
                    indices[k] = closestIndex;
                }

                for (int j = 0; j < indices.Length; j++)
                {
                    brushMesh.planes[indices[j]] = planes[j];
                }

                for (int j = solid.Sides.Count; j-- > 0;)
                {
                    VmfSolidSide side     = solid.Sides[j];
                    var          surface  = brushMesh.polygons[indices[j]].surface;
                    var          material = surface.brushMaterial.RenderMaterial;

                    // calculate the texture coordinates.
                    int w = 256;
                    int h = 256;
                    if (material.mainTexture != null)
                    {
                        w = material.mainTexture.width;
                        h = material.mainTexture.height;
                    }
                    var clip = new Plane(planes[j].xyz, planes[j].w);
                    CalculateTextureCoordinates(go, surface, clip, w, h, side.UAxis, side.VAxis);
                }

                // build displacements.
                foreach (DisplacementSide displacement in DisplacementSurfaces)
                {
                    // find the brush mesh polygon:
                    for (int polyidx = 0; polyidx < brushMesh.polygons.Length; polyidx++)
                    {
                        if (brushMesh.polygons[polyidx].surface == displacement.surface)
                        {
                            // find the polygon plane.
                            Plane plane = new Plane(brushMesh.planes[polyidx].xyz, brushMesh.planes[polyidx].w);

                            // find all vertices that belong to this polygon:
                            List <Vector3> vertices = new List <Vector3>();
                            {
                                var polygon   = brushMesh.polygons[polyidx];
                                var firstEdge = polygon.firstEdge;
                                var edgeCount = polygon.edgeCount;
                                var lastEdge  = firstEdge + edgeCount;
                                for (int e = firstEdge; e < lastEdge; e++)
                                {
                                    vertices.Add(brushMesh.vertices[brushMesh.halfEdges[e].vertexIndex]);
                                }
                            }
                            // reverse the winding order.
                            vertices.Reverse();

                            var first = vertices[0];
                            vertices.RemoveAt(0);
                            vertices.Add(first);

                            // build displacement:
                            BuildDisplacementSurface(go, displacement.side, displacement.surface, vertices, plane);
                        }
                    }
                }

                // finalize the brush by snapping planes and centering the pivot point.
                go.transform.position += brushMesh.CenterAndSnapPlanes();
                foreach (Transform child in go.transform)
                {
                    child.position -= go.transform.position;
                }
            }

            // iterate through all entities.
            for (int e = 0; e < world.Entities.Count; e++)
            {
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("Chisel: Importing Source Engine Map (2/3)", "Converting Hammer Entities To Chisel Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count);
#endif
                VmfEntity entity = world.Entities[e];

                // skip entities that chisel can't handle.
                switch (entity.ClassName)
                {
                case "func_areaportal":
                case "func_areaportalwindow":
                case "func_capturezone":
                case "func_changeclass":
                case "func_combine_ball_spawner":
                case "func_dustcloud":
                case "func_dustmotes":
                case "func_nobuild":
                case "func_nogrenades":
                case "func_occluder":
                case "func_precipitation":
                case "func_proprespawnzone":
                case "func_regenerate":
                case "func_respawnroom":
                case "func_smokevolume":
                case "func_viscluster":
                    continue;
                }

                // iterate through all entity solids.
                for (int i = 0; i < entity.Solids.Count; i++)
                {
                    VmfSolid solid = entity.Solids[i];

                    // don't add triggers to the scene.
                    if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                    {
                        continue;
                    }

                    // HACK: Fix me in the future!
                    // HACK: Chisel doesn't support collision brushes yet- skip them completely!
                    if (solid.Sides.Count > 0 && IsInvisibleMaterial(solid.Sides[0].Material))
                    {
                        continue;
                    }
                    // HACK: Fix me in the future!

                    // build a very large cube brush.
                    ChiselBrush go = ChiselComponentFactory.Create <ChiselBrush>(model);
                    go.definition.surfaceDefinition = new ChiselSurfaceDefinition();
                    go.definition.surfaceDefinition.EnsureSize(6);
                    BrushMesh brushMesh = new BrushMesh();
                    go.definition.brushOutline = brushMesh;
                    BrushMeshFactory.CreateBox(ref brushMesh, new Vector3(-4096, -4096, -4096), new Vector3(4096, 4096, 4096), in go.definition.surfaceDefinition);

                    // prepare for uv calculations of clip planes after cutting.
                    var planes        = new float4[solid.Sides.Count];
                    var planeSurfaces = new ChiselSurface[solid.Sides.Count];

                    // clip all the sides out of the brush.
                    for (int j = solid.Sides.Count; j-- > 0;)
                    {
                        VmfSolidSide side = solid.Sides[j];

                        // detect excluded polygons.
                        //if (IsExcludedMaterial(side.Material))
                        //    polygon.UserExcludeFromFinal = true;
                        // detect collision-only brushes.
                        //if (IsInvisibleMaterial(side.Material))
                        //    pr.IsVisible = false;

                        // find the material in the unity project automatically.
                        Material material;

                        // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'.
                        string materialName = side.Material.Replace("/", ".");
                        if (materialName.Contains("."))
                        {
                            // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'.
                            string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1);
                            material = materialSearcher.FindMaterial(new string[] { materialName, tiny });
                            if (material == null && materialSearcherWarnings.Add(materialName))
                            {
                                Debug.Log("Chisel: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project.");
                            }
                        }
                        else
                        {
                            // only try finding 'BRICKWALL052D'.
                            material = materialSearcher.FindMaterial(new string[] { materialName });
                            if (material == null && materialSearcherWarnings.Add(materialName))
                            {
                                Debug.Log("Chisel: Tried to find material '" + materialName + "' but it couldn't be found in the project.");
                            }
                        }

                        // fallback to default material.
                        if (material == null)
                        {
                            material = ChiselMaterialManager.DefaultFloorMaterial;
                        }

                        // create chisel surface for the clip.
                        ChiselSurface surface = new ChiselSurface();
                        surface.brushMaterial      = ChiselBrushMaterial.CreateInstance(material, ChiselMaterialManager.DefaultPhysicsMaterial);
                        surface.surfaceDescription = SurfaceDescription.Default;

                        // detect collision-only polygons.
                        if (IsInvisibleMaterial(side.Material))
                        {
                            surface.brushMaterial.LayerUsage &= ~LayerUsageFlags.RenderReceiveCastShadows;
                        }
                        // detect excluded polygons.
                        if (IsExcludedMaterial(side.Material))
                        {
                            surface.brushMaterial.LayerUsage &= LayerUsageFlags.CastShadows;
                            surface.brushMaterial.LayerUsage |= LayerUsageFlags.Collidable;
                        }

                        // calculate the clipping planes.
                        Plane clip = new Plane(go.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                        planes[j]        = new float4(clip.normal, clip.distance);
                        planeSurfaces[j] = surface;
                    }

                    // cut all the clipping planes out of the brush in one go.
                    brushMesh.Cut(planes, planeSurfaces);

                    // now iterate over the planes to calculate UV coordinates.
                    int[] indices = new int[solid.Sides.Count];
                    for (int k = 0; k < planes.Length; k++)
                    {
                        var   plane           = planes[k];
                        int   closestIndex    = 0;
                        float closestDistance = math.lengthsq(plane - brushMesh.planes[0]);
                        for (int j = 1; j < brushMesh.planes.Length; j++)
                        {
                            float testDistance = math.lengthsq(plane - brushMesh.planes[j]);
                            if (testDistance < closestDistance)
                            {
                                closestIndex    = j;
                                closestDistance = testDistance;
                            }
                        }
                        indices[k] = closestIndex;
                    }

                    for (int j = 0; j < indices.Length; j++)
                    {
                        brushMesh.planes[indices[j]] = planes[j];
                    }

                    for (int j = solid.Sides.Count; j-- > 0;)
                    {
                        VmfSolidSide side     = solid.Sides[j];
                        var          surface  = brushMesh.polygons[indices[j]].surface;
                        var          material = surface.brushMaterial.RenderMaterial;

                        // calculate the texture coordinates.
                        int w = 256;
                        int h = 256;
                        if (material.mainTexture != null)
                        {
                            w = material.mainTexture.width;
                            h = material.mainTexture.height;
                        }
                        var clip = new Plane(planes[j].xyz, planes[j].w);
                        CalculateTextureCoordinates(go, surface, clip, w, h, side.UAxis, side.VAxis);
                    }

                    // finalize the brush by snapping planes and centering the pivot point.
                    go.transform.position += brushMesh.CenterAndSnapPlanes();

                    // detail brushes that do not affect the CSG world.
                    //if (entity.ClassName == "func_detail")
                    //pr.IsNoCSG = true;
                    // collision only brushes.
                    //if (entity.ClassName == "func_vehicleclip")
                    //pr.IsVisible = false;
                }
            }
        }
示例#20
0
 public static void CreateBox(Vector3 size, int descriptionIndex, out BrushMesh box)
 {
     BrushMeshFactory.CreateBox(size, descriptionIndex, out box);
 }
        /// <summary>Converts a <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair into a <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</summary>
        /// <param name="controlMesh">A legacy <see cref="RealtimeCSG.Legacy.ControlMesh"/> that describes the shape of the <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</param>
        /// <param name="shape">A legacy <see cref="RealtimeCSG.Legacy.Shape"/> that describes the surfaces in the <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</param>
        /// <returns>A new <see cref="RealtimeCSG.Foundation.BrushMesh"/></returns>
        public static BrushMesh GenerateFromControlMesh(ControlMesh controlMesh, Shape shape)
        {
            if (controlMesh == null ||
                shape == null)
            {
                return(null);
            }

            if (!ControlMeshUtility.Validate(controlMesh, shape))
            {
                return(null);
            }

            var vertices    = controlMesh.Vertices;
            var srcEdges    = controlMesh.Edges;
            var srcPolygons = controlMesh.Polygons;

            if (vertices == null ||
                srcEdges == null ||
                srcPolygons == null)
            {
                return(null);
            }

            var surfaces    = shape.Surfaces;
            var texgens     = shape.TexGens;
            var texgenFlags = shape.TexGenFlags;

            if (surfaces == null ||
                texgens == null ||
                texgenFlags == null)
            {
                return(null);
            }

            var polygonCount = surfaces.Length;

            if (polygonCount != srcPolygons.Length ||
                polygonCount != texgens.Length ||
                polygonCount != texgenFlags.Length ||
                polygonCount != surfaces.Length)
            {
                return(null);
            }

            var brushMesh = new BrushMesh
            {
                polygons = new BrushMesh.Polygon[polygonCount],
                vertices = vertices.ToArray()
            };

            for (int i = 0; i < polygonCount; i++)
            {
                var polygonIndex = i;
                var surface      = surfaces[polygonIndex];
                var texGenIndex  = surface.TexGenIndex;
                var texGen       = texgens[texGenIndex];
                var flags        = texgenFlags[texGenIndex];

                brushMesh.polygons[i].polygonID = polygonIndex;
                brushMesh.polygons[i].surface   = CreateSurfaceDescription(surface, texGen, flags);
                brushMesh.polygons[i].layers    = CreateSurfaceLayer(texGen, flags);
            }

            int counter = 0;

            for (var i = 0; i < polygonCount; i++)
            {
                var polygonIndex = i;
                var edgeIndices  = srcPolygons[polygonIndex].EdgeIndices;
                brushMesh.polygons[i].firstEdge = counter;
                brushMesh.polygons[i].edgeCount = edgeIndices.Length;
                counter += edgeIndices.Length;
            }

            brushMesh.halfEdges = new BrushMesh.HalfEdge[counter];

            counter = 0;
            for (var i = 0; i < polygonCount; i++)
            {
                var polygonIndex = i;
                var edgeIndices  = srcPolygons[polygonIndex].EdgeIndices;
                for (var v = 0; v < edgeIndices.Length; v++)
                {
                    var edge = srcEdges[edgeIndices[v]];
                    brushMesh.halfEdges[counter + v].vertexIndex = edge.VertexIndex;

                    var twinIndex        = edge.TwinIndex;
                    var twinPolygonIndex = srcEdges[twinIndex].PolygonIndex;
                    var twinEdges        = srcPolygons[twinPolygonIndex].EdgeIndices;
                    var found            = false;
                    for (var t = 0; t < twinEdges.Length; t++)
                    {
                        if (twinEdges[t] == twinIndex)
                        {
                            twinIndex = t + brushMesh.polygons[twinPolygonIndex].firstEdge;
                            found     = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        return(null);
                    }

                    brushMesh.halfEdges[counter + v].twinIndex = twinIndex;
                }
                counter += edgeIndices.Length;
            }
            return(brushMesh);
        }