예제 #1
0
        // shoutouts to Aleksi Juvani for your vmf importer giving me a clue on why my textures were misaligned.
        // had to add the world space position of the brush to the calculations! https://github.com/aleksijuvani
        private static void CalculateTextureCoordinates(PrimitiveBrush pr, Polygon polygon, int textureWidth, int textureHeight, VmfAxis UAxis, VmfAxis VAxis)
        {
            UAxis.Translation = UAxis.Translation % textureWidth;
            VAxis.Translation = VAxis.Translation % textureHeight;

            if (UAxis.Translation < -textureWidth / 2f)
            {
                UAxis.Translation += textureWidth;
            }

            if (VAxis.Translation < -textureHeight / 2f)
            {
                VAxis.Translation += textureHeight;
            }

            // calculate texture coordinates.
            for (int i = 0; i < polygon.Vertices.Length; i++)
            {
                var vertex = pr.transform.position + polygon.Vertices[i].Position;

                Vector3 uaxis = new Vector3(UAxis.Vector.X, UAxis.Vector.Z, UAxis.Vector.Y);
                Vector3 vaxis = new Vector3(VAxis.Vector.X, VAxis.Vector.Z, VAxis.Vector.Y);

                var u = Vector3.Dot(vertex, uaxis) / (textureWidth * (UAxis.Scale * inchesInMeters)) + UAxis.Translation / textureWidth;
                var v = Vector3.Dot(vertex, vaxis) / (textureHeight * (VAxis.Scale * inchesInMeters)) + VAxis.Translation / textureHeight;

                polygon.Vertices[i].UV.x = u;
                polygon.Vertices[i].UV.y = -v;
            }
        }
예제 #2
0
    public static void ChamferSharpEdges(PrimitiveBrush brush, float chamferAngleThreshold, float chamferDistance, int chamferIterations)
    {
        var polygons          = new List <Polygon>(brush.GetPolygons());
        var polygonsChamfered = new List <Polygon>();

        var edgesVisited = new HashSet <VisitedEdge>();
        var edgesChamfer = new List <Edge>();

        foreach (var polygon in polygons)
        {
            var edges = polygon.GetEdges();
            foreach (var edge in edges)
            {
                var v1 = edge.Vertex1;
                var v2 = edge.Vertex2;

                if (edgesVisited.Contains(new VisitedEdge()
                {
                    pointA = v1.Position, pointB = v2.Position
                }))
                {
                    continue;
                }

                edgesVisited.Add(new VisitedEdge()
                {
                    pointA = v1.Position, pointB = v2.Position
                });
                edgesVisited.Add(new VisitedEdge()
                {
                    pointA = v1.Position, pointB = v2.Position
                });

                var edgePolygons = polygons.Where(p => Polygon.ContainsEdge(p, edge)).ToArray();
                if (edgePolygons.Length == 2)
                {
                    var normalA = edgePolygons[0].Plane.normal;
                    var normalB = edgePolygons[1].Plane.normal;

                    var angle = Vector3.Angle(normalA, normalB);
                    if (angle > chamferAngleThreshold)
                    {
                        edgesChamfer.Add(edge);
                    }
                }
            }
        }

        if (PolygonFactory.ChamferPolygons(polygons, edgesChamfer, chamferDistance, chamferIterations, out polygonsChamfered))
        {
            brush.SetPolygons(polygonsChamfered.ToArray());
            brush.Invalidate(true);
        }
    }
예제 #3
0
        /// <summary>
        /// Imports the specified map into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="map">The map to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModelBase model, T3dMap map, int scale = 64)
        {
            try
            {
                model.BeginUpdate();

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

                List <T3dActor> brushes      = map.Brushes;
                Brush[]         sabreBrushes = new Brush[brushes.Count];

                // iterate through all brush actors.
                for (int k = 0; k < brushes.Count; k++)
                {
                    // get the underlying brush data.
                    T3dActor tactor = brushes[k];
                    T3dBrush tbrush = tactor.Brush;
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count);
#endif
                    // iterate through the brush polygons.
                    Polygon[] polygons = new Polygon[tbrush.Polygons.Count];
                    for (int i = 0; i < tbrush.Polygons.Count; i++)
                    {
                        T3dPolygon tpolygon = tbrush.Polygons[i];

                        // find the material in the unity project automatically.
                        Material material = null;
                        if (!string.IsNullOrEmpty(tpolygon.Texture))
                        {
                            if (tpolygon.Texture.Contains('.'))
                            {
                                // try finding both 'PlayrShp.Ceiling.Hullwk' and 'Hullwk'.
                                string tiny = tpolygon.Texture.Substring(tpolygon.Texture.LastIndexOf('.') + 1);
                                material = materialSearcher.FindMaterial(new string[] { tpolygon.Texture, tiny });
                                if (material == null)
                                {
                                    Debug.Log("SabreCSG: Tried to find material '" + tpolygon.Texture + "' and also as '" + tiny + "' but it couldn't be found in the project.");
                                }
                            }
                            else
                            {
                                // only try finding 'Hullwk'.
                                material = materialSearcher.FindMaterial(new string[] { tpolygon.Texture });
                                if (material == null)
                                {
                                    Debug.Log("SabreCSG: Tried to find material '" + tpolygon.Texture + "' but it couldn't be found in the project.");
                                }
                            }
                        }

                        Vertex[] vertices = new Vertex[tpolygon.Vertices.Count];
                        for (int j = 0; j < tpolygon.Vertices.Count; j++)
                        {
                            // main-scale
                            // scale around pivot point.
                            Vector3 vertexPosition = ToVector3(tpolygon.Vertices[j]);
                            Vector3 pivot          = ToVector3(tactor.PrePivot);
                            Vector3 difference     = vertexPosition - pivot;
                            vertexPosition = difference.Multiply(ToVector3Raw(tactor.MainScale)) + pivot;

                            // post-scale
                            vertices[j] = new Vertex(vertexPosition.Multiply(ToVector3Raw(tactor.PostScale)) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material));
                        }

                        // detect the polygon flags.
                        bool userExcludeFromFinal = false;
                        if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0)
                        {
                            userExcludeFromFinal = true;
                        }

                        polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal);
                    }

                    // position and rotate the brushes around their pivot point.
                    Transform transform = model.CreateCustomBrush(polygons).transform;
                    transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale);
                    Vector3 axis;
                    float   angle;
                    T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis);
                    transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle);

                    PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>();
                    sabreBrushes[k] = brush;

                    object value;
                    // detect the brush mode (additive, subtractive).
                    if (tactor.Properties.TryGetValue("CsgOper", out value))
                    {
                        brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract;
                    }
                    // detect special brush flags.
                    if (tactor.Properties.TryGetValue("PolyFlags", out value))
                    {
                        T3dBrushFlags flags = (T3dBrushFlags)value;
                        if ((flags & T3dBrushFlags.Invisible) > 0)
                        {
                            brush.IsVisible = false;
                        }
                        if ((flags & T3dBrushFlags.NonSolid) > 0)
                        {
                            brush.HasCollision = false;
                        }
                        if ((flags & T3dBrushFlags.SemiSolid) > 0)
                        {
                            brush.IsNoCSG = true;
                        }
                    }
                    // detect single polygons.
                    if (polygons.Length == 1)
                    {
                        brush.IsNoCSG = true;
                    }
                }

                // add all new brushes to a group.
                string title = "Unreal Gold Map";
                if (map.Title != "")
                {
                    title += " '" + map.Title + "'";
                }
                if (map.Author != "")
                {
                    title += " (" + map.Author + ")";
                }

                GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);
                for (int i = 0; i < sabreBrushes.Length; i++)
                {
                    sabreBrushes[i].transform.SetParent(groupBrush.transform);
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }
예제 #4
0
        // shoutouts to Jasmine Mickle for your insight and UV texture coordinates code.
        private static void CalculateTextureCoordinates(PrimitiveBrush pr, Polygon polygon, int textureWidth, int textureHeight, Vector2 offset, Vector2 scale, float rotation)
        {
            // feel free to improve this uv mapping code, it has some issues.
            // • 45 degree angled walls may not have correct UV texture coordinates (are not correctly picking the dominant axis because there are two).
            // • negative vertex coordinates may not have correct UV texture coordinates.

            // calculate texture coordinates.
            for (int i = 0; i < polygon.Vertices.Length; i++)
            {
                // we scaled down the level so scale up the math here.
                var vertex = (pr.transform.position + polygon.Vertices[i].Position) * s_Scale;

                Vector2 uv = new Vector2(0, 0);

                int dominantAxis = 0; // 0 == x, 1 == y, 2 == z

                // find the axis closest to the polygon's normal.
                float[] axes =
                {
                    Mathf.Abs(polygon.Plane.normal.x),
                    Mathf.Abs(polygon.Plane.normal.z),
                    Mathf.Abs(polygon.Plane.normal.y)
                };

                // defaults to use x-axis.
                dominantAxis = 0;
                // check whether the y-axis is more likely.
                if (axes[1] > axes[dominantAxis])
                {
                    dominantAxis = 1;
                }
                // check whether the z-axis is more likely.
                if (axes[2] >= axes[dominantAxis])
                {
                    dominantAxis = 2;
                }

                // x-axis:
                if (dominantAxis == 0)
                {
                    uv.x = vertex.z;
                    uv.y = vertex.y;
                }

                // y-axis:
                if (dominantAxis == 1)
                {
                    uv.x = vertex.x;
                    uv.y = vertex.y;
                }

                // z-axis:
                if (dominantAxis == 2)
                {
                    uv.x = vertex.x;
                    uv.y = vertex.z;
                }

                // rotate the texture coordinates.
                uv = uv.Rotate(-rotation);
                // scale the texture coordinates.
                uv = uv.Divide(scale);
                // move the texture coordinates.
                uv += offset;
                // finally divide the result by the texture size.
                uv = uv.Divide(new Vector2(textureWidth, textureHeight));

                polygon.Vertices[i].UV = uv;
            }
        }
예제 #5
0
        /// <summary>
        /// Imports the specified map into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="map">The map to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModel model, T3dMap map, int scale = 64)
        {
            try
            {
                model.BeginUpdate();

                List <T3dActor> brushes      = map.Brushes;
                Brush[]         sabreBrushes = new Brush[brushes.Count];

                // iterate through all brush actors.
                for (int k = 0; k < brushes.Count; k++)
                {
                    // get the underlying brush data.
                    T3dActor tactor = brushes[k];
                    T3dBrush tbrush = tactor.Brush;
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count);
#endif
                    // iterate through the brush polygons.
                    Polygon[] polygons = new Polygon[tbrush.Polygons.Count];
                    for (int i = 0; i < tbrush.Polygons.Count; i++)
                    {
                        T3dPolygon tpolygon = tbrush.Polygons[i];

                        // find the material in the unity project automatically.
                        Material material = FindMaterial(tpolygon.Texture);

                        Vertex[] vertices = new Vertex[tpolygon.Vertices.Count];
                        for (int j = 0; j < tpolygon.Vertices.Count; j++)
                        {
                            vertices[j] = new Vertex(ToVector3(tpolygon.Vertices[j]) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material));
                        }

                        // detect the polygon flags.
                        bool userExcludeFromFinal = false;
                        if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0)
                        {
                            userExcludeFromFinal = true;
                        }

                        polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal);
                    }

                    // position and rotate the brushes.
                    Transform transform = model.CreateCustomBrush(polygons).transform;
                    transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale);
                    Vector3 axis;
                    float   angle;
                    T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis);
                    transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle);

                    PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>();
                    sabreBrushes[k] = brush;

                    object value;
                    // detect the brush mode (additive, subtractive).
                    if (tactor.Properties.TryGetValue("CsgOper", out value))
                    {
                        brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract;
                    }
                    // detect special brush flags.
                    if (tactor.Properties.TryGetValue("PolyFlags", out value))
                    {
                        T3dBrushFlags flags = (T3dBrushFlags)value;
                        if ((flags & T3dBrushFlags.Invisible) > 0)
                        {
                            brush.IsVisible = false;
                        }
                        if ((flags & T3dBrushFlags.NonSolid) > 0)
                        {
                            brush.HasCollision = false;
                        }
                        if ((flags & T3dBrushFlags.SemiSolid) > 0)
                        {
                            brush.IsNoCSG = true;
                        }
                    }
                    // detect single polygons.
                    if (polygons.Length == 1)
                    {
                        brush.IsNoCSG = true;
                    }
                }

                // add all new brushes to a group.
                string title = "Unreal Gold Map";
                if (map.Title != "")
                {
                    title += " '" + map.Title + "'";
                }
                if (map.Author != "")
                {
                    title += " (" + map.Author + ")";
                }

                GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);
                for (int i = 0; i < sabreBrushes.Length; i++)
                {
                    sabreBrushes[i].transform.SetParent(groupBrush.transform);
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }