コード例 #1
0
        /// <summary>
        /// Scales the brush by a local Vector3 scale from its pivot
        /// </summary>
        /// <param name="brush">The brush to be rescaled</param>
        /// <param name="rescaleValue">Local scale to apply</param>
        public static void Scale(PrimitiveBrush brush, Vector3 scaleValue)
        {
            Polygon[] polygons = brush.GetPolygons();

            for (int i = 0; i < polygons.Length; i++)
            {
                Polygon polygon = polygons[i];

                polygons[i].CalculatePlane();
                Vector3 previousPlaneNormal = polygons[i].Plane.normal;

                int vertexCount = polygon.Vertices.Length;

                Vector3[] newPositions = new Vector3[vertexCount];
                Vector2[] newUV        = new Vector2[vertexCount];

                for (int j = 0; j < vertexCount; j++)
                {
                    newPositions[j] = polygon.Vertices[j].Position;
                    newUV[j]        = polygon.Vertices[j].UV;
                }

                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];

                    Vector3 newPosition = vertex.Position.Multiply(scaleValue);
                    newPositions[j] = newPosition;

                    newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);
                }

                // Apply all the changes to the polygon
                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    vertex.Position = newPositions[j];
                    vertex.UV       = newUV[j];
                }

                // Polygon geometry has changed, inform the polygon that it needs to recalculate its cached plane
                polygons[i].CalculatePlane();

                Vector3 newPlaneNormal = polygons[i].Plane.normal;

                // Find the rotation from the original polygon plane to the new polygon plane
                Quaternion normalRotation = Quaternion.FromToRotation(previousPlaneNormal, newPlaneNormal);

                // Rotate all the vertex normals by the new rotation
                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    vertex.Normal = normalRotation * vertex.Normal;
                }
            }
#if UNITY_EDITOR
            EditorHelper.SetDirty(brush);
#endif
            brush.Invalidate(true);
        }
コード例 #2
0
 /// <summary>
 /// Generates the UV coordinates for a <see cref="Polygon"/> automatically.
 /// </summary>
 /// <param name="polygon">The polygon to be updated.</param>
 private void GenerateUvCoordinates(Polygon polygon)
 {
     foreach (Vertex vertex in polygon.Vertices)
     {
         vertex.UV = GeometryHelper.GetUVForPosition(polygon, vertex.Position);
     }
 }
コード例 #3
0
        public static Vector2 GetUVOffset(Polygon polygon)
        {
            Vertex vertex1;
            Vertex vertex2;
            Vertex vertex3;

            // Get three vertices which will reliably give us good UV information (i.e. not collinear)
            SurfaceUtility.GetPrimaryPolygonDescribers(polygon, out vertex1, out vertex2, out vertex3);

            Vector2 newUV = GeometryHelper.GetUVForPosition(vertex1.Position,
                                                            vertex2.Position,
                                                            vertex3.Position,
                                                            vertex1.UV,
                                                            vertex2.UV,
                                                            vertex3.UV,
                                                            polygon.GetCenterPoint());

            return(newUV);
        }
コード例 #4
0
        public override void PerformWeld()
        {
            // New position for the vertices is their center
            Vector3 newPosition = Vector3.zero;

            for (int i = 0; i < sourceVertices.Count; i++)
            {
                newPosition += sourceVertices[i].Position;
            }
            newPosition /= sourceVertices.Count;

            // Update all the selected vertices UVs
            for (int i = 0; i < sourceVertices.Count; i++)
            {
                Polygon polygon = vertexPolygonMappings[sourceVertices[i]];
                sourceVertices[i].UV = GeometryHelper.GetUVForPosition(polygon, newPosition);
            }

            // Update all the selected vertices to their new position
            for (int i = 0; i < sourceVertices.Count; i++)
            {
                sourceVertices[i].Position = newPosition;
            }
        }
コード例 #5
0
        public void SnapSelectedVertices(bool isAbsoluteGrid)
        {
            // So we know which polygons need to have their normals recalculated
            List <Polygon> affectedPolygons = new List <Polygon>();

            foreach (PrimitiveBrush brush in targetBrushes)
            {
                Polygon[] polygons = brush.GetPolygons();

                for (int i = 0; i < polygons.Length; i++)
                {
                    Polygon polygon = polygons[i];

                    int vertexCount = polygon.Vertices.Length;

                    Vector3[] newPositions = new Vector3[vertexCount];
                    Vector2[] newUV        = new Vector2[vertexCount];

                    for (int j = 0; j < vertexCount; j++)
                    {
                        newPositions[j] = polygon.Vertices[j].Position;
                        newUV[j]        = polygon.Vertices[j].UV;
                    }

                    bool polygonAffected = false;
                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        if (selectedVertices.ContainsKey(vertex))
                        {
                            Vector3 newPosition = vertex.Position;

                            float snapDistance = CurrentSettings.PositionSnapDistance;
                            if (isAbsoluteGrid)
                            {
                                newPosition = brush.transform.TransformPoint(newPosition);
                            }
                            newPosition = MathHelper.RoundVector3(newPosition, snapDistance);
                            if (isAbsoluteGrid)
                            {
                                newPosition = brush.transform.InverseTransformPoint(newPosition);
                            }

                            newPositions[j] = newPosition;

                            newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);

                            polygonAffected = true;
                        }
                    }

                    if (polygonAffected)
                    {
                        affectedPolygons.Add(polygon);
                    }

                    // Apply all the changes to the polygon
                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        vertex.Position = newPositions[j];
                        vertex.UV       = newUV[j];
                    }

                    polygon.CalculatePlane();
                }
            }

            if (affectedPolygons.Count > 0)
            {
                for (int i = 0; i < affectedPolygons.Count; i++)
                {
                    affectedPolygons[i].ResetVertexNormals();
                }

                foreach (PrimitiveBrush brush in targetBrushes)
                {
                    brush.Invalidate(true);

                    brush.BreakTypeRelation();
                }
            }
        }
コード例 #6
0
        public void TranslateSelectedVertices(Vector3 worldDelta)
        {
            // So we know which polygons need to have their normals recalculated
            List <Polygon> affectedPolygons = new List <Polygon>();

            foreach (PrimitiveBrush brush in targetBrushes)
            {
                Polygon[] polygons   = brush.GetPolygons();
                Vector3   localDelta = brush.transform.InverseTransformDirection(worldDelta);

                for (int i = 0; i < polygons.Length; i++)
                {
                    Polygon polygon = polygons[i];

                    int vertexCount = polygon.Vertices.Length;

                    Vector3[] newPositions = new Vector3[vertexCount];
                    Vector2[] newUV        = new Vector2[vertexCount];

                    for (int j = 0; j < vertexCount; j++)
                    {
                        newPositions[j] = polygon.Vertices[j].Position;
                        newUV[j]        = polygon.Vertices[j].UV;
                    }

                    bool polygonAffected = false;

                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        if (selectedVertices.ContainsKey(vertex))
                        {
                            Vector3 startPosition = startPositions[vertex];
                            Vector3 newPosition   = vertex.Position + localDelta;

                            Vector3 accumulatedDelta = newPosition - startPosition;

                            if (CurrentSettings.PositionSnappingEnabled)
                            {
                                float snapDistance = CurrentSettings.PositionSnapDistance;
                                //							newPosition = targetBrush.transform.TransformPoint(newPosition);
                                accumulatedDelta = MathHelper.RoundVector3(accumulatedDelta, snapDistance);
                                //							newPosition = targetBrush.transform.InverseTransformPoint(newPosition);
                            }

                            if (accumulatedDelta != Vector3.zero)
                            {
                                newPosition = startPosition + accumulatedDelta;

                                newPositions[j] = newPosition;

                                newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);

                                polygonAffected = true;
                            }
                        }
                    }

                    if (polygonAffected)
                    {
                        affectedPolygons.Add(polygon);
                    }

                    // Apply all the changes to the polygon
                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        vertex.Position = newPositions[j];
                        vertex.UV       = newUV[j];
                    }

                    polygon.CalculatePlane();
                }
            }

            if (affectedPolygons.Count > 0)
            {
                for (int i = 0; i < affectedPolygons.Count; i++)
                {
                    affectedPolygons[i].ResetVertexNormals();
                }

                foreach (PrimitiveBrush brush in targetBrushes)
                {
                    brush.Invalidate(true);

                    brush.BreakTypeRelation();
                }
            }
        }
コード例 #7
0
        public static void DisplacePolygons(Polygon[] polygons, float distance)
        {
            // Used for determining if two vertices are the same
            Polygon.VertexComparerEpsilon vertexComparer = new Polygon.VertexComparerEpsilon();
            // Used for determining if two positions or normals are the same
            Polygon.Vector3ComparerEpsilon vectorComparer = new Polygon.Vector3ComparerEpsilon();

            // Group overlapping positions and also track their normals
            List <List <Vertex> >  groupedVertices = new List <List <Vertex> >();
            List <List <Vector3> > groupedNormals  = new List <List <Vector3> >();

            // Maps back from a vertex to the polygon it came from, used for UV calculation
            Dictionary <Vertex, Polygon> vertexPolygonMappings = new Dictionary <Vertex, Polygon>();

            for (int polygonIndex = 0; polygonIndex < polygons.Length; polygonIndex++)
            {
                Vertex[] vertices = polygons[polygonIndex].Vertices;

                // Group the selected vertices into clusters
                for (int vertexIndex = 0; vertexIndex < vertices.Length; vertexIndex++)
                {
                    Vertex sourceVertex = vertices[vertexIndex];

                    vertexPolygonMappings[sourceVertex] = polygons[polygonIndex];

                    bool added = false;

                    for (int groupIndex = 0; groupIndex < groupedVertices.Count; groupIndex++)
                    {
                        if (groupedVertices[groupIndex].Contains(sourceVertex, vertexComparer))
                        {
                            groupedVertices[groupIndex].Add(sourceVertex);
                            // Add the normal of the polygon if it hasn't already been added (this prevents issues with two polygons that are coplanar)
                            if (!groupedNormals[groupIndex].Contains(polygons[polygonIndex].Plane.normal, vectorComparer))
                            {
                                groupedNormals[groupIndex].Add(polygons[polygonIndex].Plane.normal);
                            }
                            added = true;
                            break;
                        }
                    }

                    if (!added)
                    {
                        groupedVertices.Add(new List <Vertex>()
                        {
                            sourceVertex
                        });
                        groupedNormals.Add(new List <Vector3>()
                        {
                            polygons[polygonIndex].Plane.normal
                        });
                    }
                }
            }

            List <List <Vector3> > groupedPositions = new List <List <Vector3> >();
            List <List <Vector2> > groupedUV        = new List <List <Vector2> >();

            // Calculate the new positions and UVs, but don't assign them as they must be calculated in one go
            for (int i = 0; i < groupedVertices.Count; i++)
            {
                groupedPositions.Add(new List <Vector3>());
                groupedUV.Add(new List <Vector2>());

                for (int j = 0; j < groupedVertices[i].Count; j++)
                {
                    Vector3 position = groupedVertices[i][j].Position;
                    for (int k = 0; k < groupedNormals[i].Count; k++)
                    {
                        position += groupedNormals[i][k] * distance;
                    }
                    Polygon primaryPolygon = vertexPolygonMappings[groupedVertices[i][j]];

                    Vector2 uv = GeometryHelper.GetUVForPosition(primaryPolygon, position);
                    groupedPositions[i].Add(position);
                    groupedUV[i].Add(uv);
                }
            }

            // Apply the new positions and UVs now that they've all been calculated
            for (int i = 0; i < groupedVertices.Count; i++)
            {
                for (int j = 0; j < groupedVertices[i].Count; j++)
                {
                    Vertex vertex = groupedVertices[i][j];
                    vertex.Position = groupedPositions[i][j];
                    vertex.UV       = groupedUV[i][j];
                }
            }

            // Polygon planes have moved, so recalculate them
            for (int polygonIndex = 0; polygonIndex < polygons.Length; polygonIndex++)
            {
                polygons[polygonIndex].CalculatePlane();
            }
        }
コード例 #8
0
        /// <summary>
        /// Translates the specified vertices by a position delta (local to the brush) and updates the UVs
        /// </summary>
        /// <param name="brush">Brush from which the vertices belong.</param>
        /// <param name="specifiedVertices">Specified vertices to be translated.</param>
        /// <param name="localDelta">Local positional delta.</param>
        public static void TranslateSpecifiedVertices(Brush brush, List <Vertex> specifiedVertices, Vector3 localDelta)
        {
            Polygon.Vector3ComparerEpsilon positionComparer = new Polygon.Vector3ComparerEpsilon();

            // Cache the positions as the position of vertices will change while in the for loop
            List <Vector3> specifiedPositions = specifiedVertices.Select(item => item.Position).ToList();

            // So we know which polygons need to have their normals recalculated
            List <Polygon> affectedPolygons = new List <Polygon>();

            Polygon[] polygons = brush.GetPolygons();

            for (int i = 0; i < polygons.Length; i++)
            {
                Polygon polygon = polygons[i];

                int vertexCount = polygon.Vertices.Length;

                Vector3[] newPositions = new Vector3[vertexCount];
                Vector2[] newUV        = new Vector2[vertexCount];

                for (int j = 0; j < vertexCount; j++)
                {
                    newPositions[j] = polygon.Vertices[j].Position;
                    newUV[j]        = polygon.Vertices[j].UV;
                }

                bool polygonAffected = false;

                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    if (specifiedPositions.Contains(vertex.Position, positionComparer))
                    {
                        Vector3 newPosition = vertex.Position + localDelta;

                        newPositions[j] = newPosition;

                        newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);

                        polygonAffected = true;
                    }
                }

                if (polygonAffected)
                {
                    affectedPolygons.Add(polygon);
                }

                // Apply all the changes to the polygon
                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    vertex.Position = newPositions[j];
                    vertex.UV       = newUV[j];
                }

                polygon.CalculatePlane();
            }

            if (affectedPolygons.Count > 0)
            {
                for (int i = 0; i < affectedPolygons.Count; i++)
                {
                    affectedPolygons[i].ResetVertexNormals();
                }
            }
        }
コード例 #9
0
        public override void PerformWeld()
        {
            List <List <Vertex> > groupedVertices = new List <List <Vertex> >();

            VertexComparerTolerance comparer = new VertexComparerTolerance(tolerance);

            // Group the selected vertices into clusters
            for (int sourceVertexIndex = 0; sourceVertexIndex < sourceVertices.Count; sourceVertexIndex++)
            {
                Vertex sourceVertex = sourceVertices[sourceVertexIndex];

                bool added = false;

                for (int groupIndex = 0; groupIndex < groupedVertices.Count; groupIndex++)
                {
                    if (groupedVertices[groupIndex].Contains(sourceVertex, comparer))
                    {
                        groupedVertices[groupIndex].Add(sourceVertex);
                        added = true;
                        break;
                    }
                }

                if (!added)
                {
                    groupedVertices.Add(new List <Vertex>()
                    {
                        sourceVertex
                    });
                }
            }


            for (int groupIndex = 0; groupIndex < groupedVertices.Count; groupIndex++)
            {
                List <Vertex> vertices = groupedVertices[groupIndex];

                // Ignoring any groups that only contain one vertex
                if (vertices.Count > 1)
                {
                    // New position for the vertices is their center
                    Vector3 newPosition = Vector3.zero;
                    for (int vertexIndex = 0; vertexIndex < vertices.Count; vertexIndex++)
                    {
                        newPosition += vertices[vertexIndex].Position;
                    }
                    newPosition /= vertices.Count;

                    // Update all the selected vertices UVs
                    for (int vertexIndex = 0; vertexIndex < vertices.Count; vertexIndex++)
                    {
                        Polygon polygon = vertexPolygonMappings[vertices[vertexIndex]];
                        vertices[vertexIndex].UV = GeometryHelper.GetUVForPosition(polygon, newPosition);
                    }

                    // Update all the selected vertices to their new position
                    for (int vertexIndex = 0; vertexIndex < vertices.Count; vertexIndex++)
                    {
                        vertices[vertexIndex].Position = newPosition;
                    }
                }
            }
        }
コード例 #10
0
        private void CreateBrush(List <Vector3> positions)
        {
            Polygon sourcePolygon = PolygonFactory.ConstructPolygon(positions, true);

            // Early out if it wasn't possible to create the polygon
            if (sourcePolygon == null)
            {
                return;
            }

            if (activePolygon != null)
            {
                for (int i = 0; i < sourcePolygon.Vertices.Length; i++)
                {
                    Vector2 newUV = GeometryHelper.GetUVForPosition(activePolygon, sourcePolygon.Vertices[i].Position);
                    sourcePolygon.Vertices[i].UV = newUV;
                }
            }

            Vector3 planeNormal = GetActivePlane().normal;

            //			Debug.Log(Vector3.Dot(sourcePolygon.Plane.normal, planeNormal));

            // Flip the polygon if the winding order is wrong
            if (Vector3.Dot(sourcePolygon.Plane.normal, planeNormal) < 0)
            {
                sourcePolygon.Flip();

                // Need to flip the UVs across the U (X) direction
                for (int i = 0; i < sourcePolygon.Vertices.Length; i++)
                {
                    Vector2 uv = sourcePolygon.Vertices[i].UV;
                    uv.x = 1 - uv.x;
                    sourcePolygon.Vertices[i].UV = uv;
                }
            }

            float   extrusionDistance = 1;
            Vector3 positionOffset    = Vector3.zero;

            if (selectingHeight)
            {
                extrusionDistance = prismHeight;
            }
            else
            {
                if (activePolygon != null && activeBrush != null)
                {
                    extrusionDistance = activeBrush.CalculateExtentsInAxis(planeNormal);
                }
                else
                {
                    Brush lastSelectedBrush = csgModel.LastSelectedBrush;
                    if (lastSelectedBrush != null)
                    {
                        Bounds lastSelectedBrushBounds = lastSelectedBrush.GetBoundsTransformed();

                        for (int i = 0; i < 3; i++)
                        {
                            if (!planeNormal[i].EqualsWithEpsilon(0))
                            {
                                if (lastSelectedBrushBounds.size[i] != 0)
                                {
                                    extrusionDistance = lastSelectedBrushBounds.size[i];

                                    if (planeNormal[i] > 0)
                                    {
                                        positionOffset[i] = lastSelectedBrushBounds.center[i] - lastSelectedBrushBounds.extents[i];
                                    }
                                    else
                                    {
                                        positionOffset[i] = lastSelectedBrushBounds.center[i] + lastSelectedBrushBounds.extents[i];
                                    }
                                }
                            }
                        }
                    }
                }

                // Subtractions should go through
                if (csgMode == CSGMode.Subtract)
                {
                    sourcePolygon.Flip();
                }
            }

            Quaternion rotation;

            Polygon[] polygons;
            SurfaceUtility.ExtrudePolygon(sourcePolygon, extrusionDistance, out polygons, out rotation);

            GameObject newObject = csgModel.CreateCustomBrush(polygons);

            PrimitiveBrush newBrush = newObject.GetComponent <PrimitiveBrush>();

            newObject.transform.rotation  = rotation;
            newObject.transform.position += positionOffset;

            if (activePolygon != null &&
                activePolygon.Material != csgModel.GetDefaultMaterial())
            {
                for (int i = 0; i < polygons.Length; i++)
                {
                    polygons[i].Material = activePolygon.Material;
                }
            }
            // Finally give the new brush the other set of polygons
            newBrush.SetPolygons(polygons, true);

            newBrush.Mode = csgMode;

            newBrush.ResetPivot();

            // Use this brush as the basis for drawing the next brush
            csgModel.SetLastSelectedBrush(newBrush);

            Undo.RegisterCreatedObjectUndo(newObject, "Draw Brush");
        }
コード例 #11
0
ファイル: CurvedStairBrush.cs プロジェクト: Ciziu/trancepcja
        public override void Invalidate(bool polygonsChanged)
        {
            base.Invalidate(polygonsChanged);

            ////////////////////////////////////////////////////////////////////
            // a little hack to detect the user manually resizing the bounds. //
            // we use this to automatically add steps for barnaby.            //
            // it's probably good to build a more 'official' way to detect    //
            // user scaling events in compound brushes sometime.              //
            if (m_LastKnownExtents != localBounds.extents)        //
            {                                                     //
                // undo any position movement.                                //
                transform.localPosition = m_LastKnownPosition;    //
                // user is trying to scale up.                                //
                if (localBounds.extents.y > m_LastKnownExtents.y) //
                {                                                 //
                    numSteps          += 1;                       //
                    m_LastKnownExtents = localBounds.extents;     //
                    Invalidate(true);                             // recusion! <3                         //
                    return;                                       //
                }                                                 //
                // user is trying to scale down.                              //
                if (localBounds.extents.y < m_LastKnownExtents.y) //
                {                                                 //
                    numSteps -= 1;                                //
                    if (numSteps < 1)
                    {
                        numSteps = 1;                         //
                    }
                    m_LastKnownExtents = localBounds.extents; //
                    Invalidate(true);                         // recusion! <3                         //
                    return;                                   //
                }                                             //
            }                                                 //
            ////////////////////////////////////////////////////////////////////

            // local variables
            List <Vector3> vertexPositions = new List <Vector3>();
            Plane          plane;
            Vector3        rotateStep = new Vector3();
            Vector3        vertex = new Vector3(), newVertex = new Vector3();
            float          adjustment;
            int            innerStart, outerStart, bottomInnerStart, bottomOuterStart;

            // begin
            rotateStep.z = angleOfCurve / numSteps;

            if (counterClockwise)
            {
                rotateStep.z *= -1;
            }

            // generate the inner curve points.
            innerStart = vertexPositions.Count;
            vertex.x   = innerRadius;
            for (int x = 0; x < (numSteps + 1); x++)
            {
                if (x == 0)
                {
                    adjustment = addToFirstStep;
                }
                else
                {
                    adjustment = 0;
                }

                newVertex = Quaternion.Euler(rotateStep * x) * vertex;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y));
                vertex.z += stepHeight;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
            }

            // generate the outer curve points.
            outerStart = vertexPositions.Count;
            vertex.x   = innerRadius + stepWidth;
            vertex.z   = 0;
            for (int x = 0; x < (numSteps + 1); x++)
            {
                if (x == 0)
                {
                    adjustment = addToFirstStep;
                }
                else
                {
                    adjustment = 0;
                }

                newVertex = Quaternion.Euler(rotateStep * x) * vertex;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y));
                vertex.z += stepHeight;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
            }

            // generate the bottom inner curve points.
            bottomInnerStart = vertexPositions.Count;
            vertex.x         = innerRadius;
            vertex.z         = 0;
            for (int x = 0; x < (numSteps + 1); x++)
            {
                newVertex = Quaternion.Euler(rotateStep * x) * vertex;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z - addToFirstStep, newVertex.y));
            }

            // generate the bottom outer curve points.
            bottomOuterStart = vertexPositions.Count;
            vertex.x         = innerRadius + stepWidth;
            for (int x = 0; x < (numSteps + 1); x++)
            {
                newVertex = Quaternion.Euler(rotateStep * x) * vertex;
                vertexPositions.Add(new Vector3(newVertex.x, vertex.z - addToFirstStep, newVertex.y));
            }

            // vertex indices to easily flip faces for the counter clockwise mode.
            int index0 = 0;
            int index1 = 1;
            int index2 = 2;
            int index3 = 3;

            // flip faces if counter clockwise mode is enabled.
            if (counterClockwise)
            {
                index0 = 2;
                index1 = 1;
                index2 = 0;
                index3 = 3;
            }

            // we calculate the bounds of the output csg.
            Bounds csgBounds = new Bounds();

            // iterate through the brushes we received:
            int brushCount = BrushCount;

            for (int i = 0; i < brushCount; i++)
            {
                // copy our csg information to our child brushes.
                generatedBrushes[i].Mode         = this.Mode;
                generatedBrushes[i].IsNoCSG      = this.IsNoCSG;
                generatedBrushes[i].IsVisible    = this.IsVisible;
                generatedBrushes[i].HasCollision = this.HasCollision;

                // retrieve the polygons from the current cube brush.
                Polygon[] polygons = generatedBrushes[i].GetPolygons();

                // +-----------------------------------------------------+
                // | Cube Polygons                                       |
                // +--------+--------+--------+--------+--------+--------+
                // | Poly:0 | Poly:1 | Poly:2 | Poly:3 | Poly:4 | Poly:5 |
                // +-----------------------------------------------------+
                // | Back   | Left   | Right  | Front  | Bottom | Top    |
                // +--------+--------+--------+--------+--------+--------+

                // retrieve the vertices of the top polygon.
                Vertex[] vertices = polygons[5].Vertices;

                // step top.
                vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
                vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1];
                vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
                vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2];

                // update uv coordinates to prevent distortions using barnaby's genius utilities.
                vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 2]);
                vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 1]);
                vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 1]);
                vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 2]);



                // retrieve the vertices of the front polygon.
                vertices = polygons[3].Vertices;

                // step front.
                vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1];
                vertices[index1].Position = vertexPositions[bottomOuterStart + i];
                vertices[index2].Position = vertexPositions[bottomInnerStart + i];
                vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1];

                // calculate a normal using a virtual plane.
                plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
                vertices[index0].Normal = plane.normal;
                vertices[index1].Normal = plane.normal;
                vertices[index2].Normal = plane.normal;
                vertices[index3].Normal = plane.normal;



                // retrieve the vertices of the left polygon.
                vertices = polygons[1].Vertices;

                // inner curve.
                vertices[index0].Position = vertexPositions[bottomInnerStart + i + 1];
                vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2];
                vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1];
                vertices[index3].Position = vertexPositions[bottomInnerStart + i];

                // calculate a normal using a virtual plane.
                plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
                vertices[index0].Normal = plane.normal;
                vertices[index1].Normal = plane.normal;
                vertices[index2].Normal = plane.normal;
                vertices[index3].Normal = plane.normal;



                // retrieve the vertices of the right polygon.
                vertices = polygons[2].Vertices;

                // outer curve.
                vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2];
                vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
                vertices[index2].Position = vertexPositions[bottomOuterStart + i];
                vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1];

                // calculate a normal using a virtual plane.
                plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
                vertices[index0].Normal = plane.normal;
                vertices[index1].Normal = plane.normal;
                vertices[index2].Normal = plane.normal;
                vertices[index3].Normal = plane.normal;



                // retrieve the vertices of the bottom polygon.
                vertices = polygons[4].Vertices;

                // bottom.
                vertices[index0].Position = vertexPositions[bottomOuterStart + i];
                vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1];
                vertices[index2].Position = vertexPositions[bottomInnerStart + i + 1];
                vertices[index3].Position = vertexPositions[bottomInnerStart + i];

                // update uv coordinates to prevent distortions using barnaby's genius utilities.
                vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i]);
                vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i + 1]);
                vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i + 1]);
                vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i]);



                // retrieve the vertices of the back polygon.
                vertices = polygons[0].Vertices;

                // back panel.
                vertices[index0].Position = vertexPositions[bottomOuterStart + i + 1];
                vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2];
                vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2];
                vertices[index3].Position = vertexPositions[bottomInnerStart + i + 1];

                // calculate a normal using a virtual plane.
                plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position);
                vertices[index0].Normal = plane.normal;
                vertices[index1].Normal = plane.normal;
                vertices[index2].Normal = plane.normal;
                vertices[index3].Normal = plane.normal;

                generatedBrushes[i].Invalidate(true);
                csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
            }

            // apply the generated csg bounds.
            localBounds         = csgBounds;
            m_LastKnownExtents  = localBounds.extents;
            m_LastKnownPosition = transform.localPosition;
        }
コード例 #12
0
        public void TranslateSelectedVertices(Vector3 worldDelta)
        {
            foreach (PrimitiveBrush brush in targetBrushes)
            {
                bool anyAffected = false;

                Polygon[] polygons   = brush.GetPolygons();
                Vector3   localDelta = brush.transform.InverseTransformDirection(worldDelta);

                for (int i = 0; i < polygons.Length; i++)
                {
                    Polygon polygon = polygons[i];

                    polygon.CalculatePlane();
                    Vector3 previousPlaneNormal = polygons[i].Plane.normal;

                    int vertexCount = polygon.Vertices.Length;

                    Vector3[] newPositions = new Vector3[vertexCount];
                    Vector2[] newUV        = new Vector2[vertexCount];

                    for (int j = 0; j < vertexCount; j++)
                    {
                        newPositions[j] = polygon.Vertices[j].Position;
                        newUV[j]        = polygon.Vertices[j].UV;
                    }

                    bool polygonAffected = false;

                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        if (selectedVertices.ContainsKey(vertex))
                        {
                            Vector3 startPosition = startPositions[vertex];
                            Vector3 newPosition   = vertex.Position + localDelta;

                            Vector3 accumulatedDelta = newPosition - startPosition;

                            if (CurrentSettings.PositionSnappingEnabled)
                            {
                                float snapDistance = CurrentSettings.PositionSnapDistance;
                                //							newPosition = targetBrush.transform.TransformPoint(newPosition);
                                accumulatedDelta = MathHelper.RoundVector3(accumulatedDelta, snapDistance);
                                //							newPosition = targetBrush.transform.InverseTransformPoint(newPosition);
                            }

                            if (accumulatedDelta != Vector3.zero)
                            {
                                newPosition = startPosition + accumulatedDelta;

                                newPositions[j] = newPosition;

                                newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);

                                polygonAffected = true;
                                anyAffected     = true;
                            }
                        }
                    }

                    // Apply all the changes to the polygon
                    for (int j = 0; j < vertexCount; j++)
                    {
                        Vertex vertex = polygon.Vertices[j];
                        vertex.Position = newPositions[j];
                        vertex.UV       = newUV[j];
                    }

                    if (polygonAffected)
                    {
                        // Polygon geometry has changed, inform the polygon that it needs to recalculate its cached plane
                        polygons[i].CalculatePlane();

                        Vector3 newPlaneNormal = polygons[i].Plane.normal;

                        // Find the rotation from the original polygon plane to the new polygon plane
                        Quaternion normalRotation = Quaternion.FromToRotation(previousPlaneNormal, newPlaneNormal);

                        // Update the affected normals so they are rotated by the rotational difference of the polygon from translation
                        for (int j = 0; j < vertexCount; j++)
                        {
                            Vertex vertex = polygon.Vertices[j];
                            vertex.Normal = normalRotation * vertex.Normal;
                        }
                    }
                }

                if (anyAffected)                // If any polygons have changed
                {
                    // Mark the polygons and brush as having changed
                    brush.Invalidate(true);

                    // Assume that the brush no longer resembles it's base shape, this has false positives but that's not a big issue
                    brush.BreakTypeRelation();
                }
            }
        }