public void PointModified(List <VolumePoint> data)
        {
            HUtils.log();

            int dataCount = data.Count;

            if (data.Count == 0)
            {
                return;
            }
            int pointCount = numberOfPoints;

            for (int d = 0; d < dataCount; d++)
            {
                VolumePoint point = data[d];
                if (!point.moved)
                {
                    continue;
                }
                for (int p = 0; p < pointCount; p++)
                {
                    if (point.lastPosition == _points[p].position)
                    {
                        _points[p].position = point.position;
                        _points[p].MarkUnmodified();
                    }
                }
            }
            if (isModified)
            {
                MarkModified();
            }
        }
        public void AddPoint(Vector2Int newPosition)
        {
            VolumePoint newPoint = new VolumePoint(newPosition);

            _points.Add(newPoint);
            CheckVolume();
            MarkModified();
        }
Exemple #3
0
        public void AddPoint(Vector2Int newPosition)
        {
            HUtils.log();
            Debug.Log("Volume.cs AddPoint(Vector2Int newPosition) newPosition=(" + newPosition.x + "," + newPosition.y + ")");
            VolumePoint newPoint = new VolumePoint(newPosition);

            _points.Add(newPoint);
            CheckVolume();
            MarkModified();
        }
Exemple #4
0
        public VolumePoint Clone()
        {
            VolumePoint output = new VolumePoint(_position);

            output._controlA   = _controlA;
            output._controlB   = _controlB;
            output._curveStyle = _curveStyle;
            output._render     = _render;
            output._facade     = _facade;
            return(output);
        }
        private void CheckInternalPointMovement(VolumePoint modifiedPoint)
        {
            int pointCount = numberOfPoints;

            for (int p = 0; p < pointCount; p++)
            {
                VolumePoint point = _points[p];
                if (modifiedPoint == point)
                {
                    continue;
                }
                if (modifiedPoint.lastPosition == point.position)
                {
                    point.position = modifiedPoint.position;
                    _points[p].MarkUnmodified();
                }
            }
        }
        public static bool HasNullFacades(IBuilding building)
        {
            int planCount = building.numberOfPlans;

            for (int pl = 0; pl < planCount; pl++)
            {
                IVolume plan        = building[pl];
                int     facadeCount = plan.numberOfPoints;
                for (int f = 0; f < facadeCount; f++)
                {
                    VolumePoint facadeData = plan[f];
                    if (facadeData.facade == null)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #7
0
        public static void RoofFacadeInspectorGUI(Volume volume, int index)
        {
            VolumePoint point = volume[index];

//            GUIStyle facadeLabelStyle = new GUIStyle();
//            facadeLabelStyle.normal.background = new Texture2D();
            EditorGUILayout.LabelField(string.Format("Facade: {0}", index + 1));

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Is Gabled", GUILayout.Width(60));
            point.isGabled = EditorGUILayout.Toggle(point.isGabled, GUILayout.Width(20));
            EditorGUILayout.EndHorizontal();

            EditorGUI.BeginDisabledGroup(!point.isGabled);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Thickness");
            point.gableThickness = EditorGUILayout.Slider(point.gableThickness, 0.1f, 5);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Additional Height");
            point.gableHeight = EditorGUILayout.Slider(point.gableHeight, 0.1f, 5);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Simple Gable");
            point.simpleGable = EditorGUILayout.Toggle(point.simpleGable);
            EditorGUILayout.EndHorizontal();

            EditorGUI.BeginDisabledGroup(point.simpleGable);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Gable Design", GUILayout.Width(80));
            point.gableStyle = (Gable)EditorGUILayout.ObjectField(point.gableStyle, typeof(Gable), false);
            EditorGUI.EndDisabledGroup();
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();

            //            EditorGUILayout.BeginHorizontal();
            //            EditorGUILayout.LabelField("Thickness");
            //            _gable.thickness = EditorGUILayout.Slider(_gable.thickness, 0.1f, 5);
            //            EditorGUILayout.EndHorizontal();
        }
Exemple #8
0
 public bool Equals(VolumePoint p)
 {
     if (p == null)
     {
         return(false);
     }
     if (_position != p._position)
     {
         return(false);
     }
     if (_controlA != p._controlA)
     {
         return(false);
     }
     if (_controlB != p._controlB)
     {
         return(false);
     }
     if (_facade != p._facade)
     {
         return(false);
     }
     return(true);
 }
        public void CalculateExternalWallAnchors()
        {
            HUtils.log();

            if (_externalFacadeWallAnchors == null)
            {
                _externalFacadeWallAnchors = new Dictionary <int, List <Vector2Int> >();
            }
            if (_externalWallAnchorsFacades == null)
            {
                _externalWallAnchorsFacades = new Dictionary <Vector2Int, List <int> >();
            }
            if (_externalWallAnchors == null)
            {
                _externalWallAnchors = new List <Vector2Int>();
            }
            _externalFacadeWallAnchors.Clear();
            _externalWallAnchorsFacades.Clear();
            _externalWallAnchors.Clear();
            int pointCount = _points.Count;

            //            int anchorCount = 0;
            for (int p = 0; p < pointCount; p++)
            {
                VolumePoint a  = _points[p];
                VolumePoint b  = _points[(p + 1) % pointCount];
                Vector2     av = a.position.vector2;
                Vector2     bv = b.position.vector2;

                _externalFacadeWallAnchors.Add(p, new List <Vector2Int>());               //new facade entry

                if (IsWallStraight(p))
                {
                    float length       = Vector2.Distance(av, bv);
                    int   wallSections = Mathf.FloorToInt(length / _minimumWallUnitLength);
                    if (wallSections < 1)
                    {
                        wallSections = 1;
                    }
                    for (int ws = 0; ws < wallSections + 1; ws++)
                    {
                        float      lerp  = ws / ((float)wallSections);
                        Vector2Int point = new Vector2Int(Vector2.Lerp(av, bv, lerp));

                        _externalFacadeWallAnchors[p].Add(point);
                        AddFacadeWallAnchors(point, p);

                        if (ws < wallSections)
                        {
                            _externalWallAnchors.Add(point);
                        }
                    }
                }
                else
                {
                    Vector2 cw0       = a.controlA.vector2;
                    Vector2 cw1       = a.controlB.vector2;
                    Vector2 last      = Vector2.zero;
                    float   arcLength = 0;
                    for (int t = 0; t < 10; t++)
                    {
                        Vector2 cp = FacadeSpline.Calculate(av, cw0, cw1, bv, t / 9f);
                        if (t > 0)
                        {
                            arcLength += Vector2.Distance(cp, last);
                        }
                        last = cp;
                    }

                    int wallSections = Mathf.FloorToInt(arcLength / _minimumWallUnitLength);
                    if (wallSections < 1)
                    {
                        wallSections = 1;
                    }
                    float      sectionLength = arcLength / Mathf.Max(wallSections - 1f, 1f);
                    int        movement      = wallSections * 10;
                    int        currentIndex  = 0;
                    Vector2    lastCP        = av;
                    Vector2    lastA         = av;
                    float      lastDist      = 0;
                    Vector2Int avi           = new Vector2Int(av);
                    _externalFacadeWallAnchors[p].Add(avi);
                    AddFacadeWallAnchors(avi, p);
                    _externalWallAnchors.Add(avi);
                    for (int m = 0; m < movement; m++)
                    {
                        float   percent = m / (float)movement;
                        Vector2 cp      = FacadeSpline.Calculate(av, cw0, cw1, bv, percent);
                        float   dist    = Vector2.Distance(lastA, cp);
                        //                        Debug.Log(dist);
                        if (dist >= sectionLength)
                        {
                            float   cpDist        = dist - lastDist;
                            float   overDist      = dist - sectionLength;
                            float   targetPercent = 1 - Mathf.Clamp01(overDist / cpDist);
                            Vector2 usePoint      = Vector2.Lerp(lastCP, cp, targetPercent);
                            lastA = usePoint;
                            currentIndex++;
                            Vector2Int upi = new Vector2Int(usePoint);
                            _externalFacadeWallAnchors[p].Add(upi);
                            AddFacadeWallAnchors(upi, p);
                            _externalWallAnchors.Add(upi);
                            if (currentIndex == wallSections - 2)
                            {
                                break;
                            }
                        }

                        lastCP   = cp;
                        lastDist = dist;
                    }
                    Vector2Int bvi = new Vector2Int(bv);
                    _externalFacadeWallAnchors[p].Add(bvi);
                    AddFacadeWallAnchors(bvi, p);
                    //                    _externalWallAnchors.Add(bvi);
                }
            }
        }
Exemple #10
0
        private static void ToMesh(ref BuildRMesh mesh, ref Shape shape, float roofBaseHeight, float meshHeight, int[] facadeIndices, IVolume volume, int submesh, Surface surface, bool generateDormers = false)
        {
            //TODO fix this error properly
            if (shape == null)
            {
                Debug.Log("ToMesh: Error to fix");
                return;
            }
            List <Edge> edges     = new List <Edge>(shape.edges);
            List <Edge> baseEdges = new List <Edge>(shape.baseEdges);

            float shapeHeight = shape.HeighestPoint();
            float heightScale = meshHeight / shapeHeight;
            bool  isFloor     = meshHeight < 0.00001f;

            Dictionary <Node, int>          shapeConnectionCount = new Dictionary <Node, int>();
            Dictionary <Node, List <Node> > shapeConnections     = new Dictionary <Node, List <Node> >();
            int edgeCount = edges.Count;

            for (int e = 0; e < edgeCount; e++)
            {
                Edge edge = edges[e];

                if (edge.length < Mathf.Epsilon)
                {
                    continue;
                }

                if (!shapeConnectionCount.ContainsKey(edge.nodeA))
                {
                    shapeConnectionCount.Add(edge.nodeA, 0);//start at zero - we need two edges to make a shape...
                    shapeConnections.Add(edge.nodeA, new List <Node> {
                        edge.nodeB
                    });
                }
                else
                {
                    shapeConnectionCount[edge.nodeA]++;
                    if (!shapeConnections[edge.nodeA].Contains(edge.nodeB))
                    {
                        shapeConnections[edge.nodeA].Add(edge.nodeB);
                    }
                }

                if (!shapeConnectionCount.ContainsKey(edge.nodeB))
                {
                    shapeConnectionCount.Add(edge.nodeB, 0);//start at zero - we need two edges to make a shape...
                    shapeConnections.Add(edge.nodeB, new List <Node> {
                        edge.nodeA
                    });
                }
                else
                {
                    shapeConnectionCount[edge.nodeB]++;
                    if (!shapeConnections[edge.nodeB].Contains(edge.nodeA))
                    {
                        shapeConnections[edge.nodeB].Add(edge.nodeA);
                    }
                }
            }

            int baseEdgeCount          = baseEdges.Count;
            List <Vector3[]> roofFaces = new List <Vector3[]>();

            for (int b = 0; b < baseEdgeCount; b++)
            {
                int  facadeIndex = facadeIndices[b];
                bool isGabled    = volume[facadeIndex].isGabled;
                if (!isGabled)
                {
                    int  facadeIndexLeft  = (facadeIndex - 1 + volume.numberOfFacades) % volume.numberOfFacades;
                    int  facadeIndexRight = (facadeIndex + 1) % volume.numberOfFacades;
                    bool isGabledLeft     = volume[facadeIndexLeft].isGabled;
                    bool isGabledRight    = volume[facadeIndexRight].isGabled;
                    Edge baseEdge         = baseEdges[b];
                    Node nodeA            = baseEdge.nodeA;
                    Node nodeB            = baseEdge.nodeB;

                    Node        currentNode = nodeA;
                    Node        lastNode    = nodeB;
                    int         itMax       = 50;
                    List <Node> edgeShape   = new List <Node>()
                    {
                        nodeA
                    };

                    while (currentNode != nodeB)
                    {
                        List <Node> nodeConnections     = shapeConnections[currentNode];
                        int         nodeConnectionCount = nodeConnections.Count;
                        float       minAngle            = Mathf.Infinity;
                        Node        nextNode            = null;
                        Vector2     currentDirection    = (currentNode.position - lastNode.position).normalized;
                        for (int n = 0; n < nodeConnectionCount; n++)
                        {
                            Node connectingNode = nodeConnections[n];
                            if (connectingNode == lastNode)
                            {
                                continue;                           //end this circus!
                            }
                            Vector2 nextDirection = (connectingNode.position - currentNode.position).normalized;
                            float   nodeAngle     = SignAngleDirection(currentDirection, nextDirection);
                            if (nodeAngle < minAngle)
                            {
                                minAngle = nodeAngle;
                                nextNode = connectingNode;
                            }
                        }
                        if (nextNode != null)
                        {
                            edgeShape.Add(nextNode);
                            lastNode    = currentNode;
                            currentNode = nextNode;
                        }


                        itMax--;
                        if (itMax < 0)
                        {
                            break;
                        }
                    }

                    int edgeShapeCount = edgeShape.Count;

                    if (edgeShapeCount == 4 && generateDormers)
                    {
                        Vector3[] edgeShapeV3 = new Vector3[4];
                        edgeShapeV3[0] = new Vector3(edgeShape[0].position.x, roofBaseHeight, edgeShape[0].position.y);
                        edgeShapeV3[1] = new Vector3(edgeShape[3].position.x, roofBaseHeight, edgeShape[3].position.y);
                        edgeShapeV3[2] = new Vector3(edgeShape[1].position.x, roofBaseHeight + meshHeight, edgeShape[1].position.y);
                        edgeShapeV3[3] = new Vector3(edgeShape[2].position.x, roofBaseHeight + meshHeight, edgeShape[2].position.y);
                        roofFaces.Add(edgeShapeV3);
                    }

                    if ((isGabledLeft || isGabledRight) && edgeShapeCount == 4)//modify shape if gables are detected
                    {
                        Vector3 p0     = edgeShape[0].position;
                        Vector3 p1     = edgeShape[3].position;
                        Vector3 p2     = edgeShape[1].position;
                        Vector3 vector = p1 - p0;
                        Vector3 dir    = vector.normalized;
                        Vector3 cross  = Vector3.Cross(Vector3.back, dir);

                        if (isGabledLeft)
                        {
                            float gableThickness = volume[facadeIndexLeft].gableThickness;
                            bool  simpleGable    = volume[facadeIndexLeft].simpleGable;
                            Gable gableStyle     = volume[facadeIndexLeft].gableStyle;
                            if (!simpleGable && gableStyle == null || !isFloor)
                            {
                                gableThickness = 0;
                            }
                            Vector3 newPointA = Vector3.Project(p2 - p1, cross) + dir * gableThickness;
                            edgeShape[1].position = edgeShape[0].position + new Vector2(newPointA.x, newPointA.y);
                        }
                        if (isGabledRight)
                        {
                            float gableThickness = volume[facadeIndexRight].gableThickness;
                            bool  simpleGable    = volume[facadeIndexRight].simpleGable;
                            Gable gableStyle     = volume[facadeIndexRight].gableStyle;
                            if (!simpleGable && gableStyle == null || !isFloor)
                            {
                                gableThickness = 0;
                            }
                            Vector3 newPointB = Vector3.Project(p2 - p1, cross) - dir * gableThickness;
                            edgeShape[2].position = edgeShape[3].position + new Vector2(newPointB.x, newPointB.y);
                        }
                    }


                    Vector3[] verts = new Vector3[edgeShapeCount];

                    Vector2[] uvs = new Vector2[edgeShapeCount];
                    Vector3   baseShapeDirection = ToV3(nodeB.position - nodeA.position).normalized;
                    float     uvAngle            = SignAngle(new Vector2(baseShapeDirection.x, baseShapeDirection.z).normalized) - 90;

                    Vector2[] faceShape = new Vector2[edgeShapeCount];
                    Vector3[] normals   = new Vector3[edgeShapeCount];
                    Vector4[] tangents  = new Vector4[edgeShapeCount];
                    Vector4   tangent   = BuildRMesh.CalculateTangent(baseShapeDirection);
                    for (int i = 0; i < edgeShapeCount; i++)
                    {
                        Vector3 newVert = new Vector3(edgeShape[i].position.x, edgeShape[i].height * heightScale + roofBaseHeight, edgeShape[i].position.y);
                        verts[i] = newVert;

                        Vector2 baseUV     = (i == 0) ? Vector2.zero : new Vector2(newVert.x - verts[0].x, newVert.z - verts[0].z);
                        Vector2 newUV      = Rotate(baseUV, uvAngle);
                        float   faceHeight = edgeShape[i].height * heightScale;
                        newUV.y = Mathf.Sqrt((newUV.y * newUV.y) + (faceHeight * faceHeight));
                        if (surface != null)
                        {
                            newUV = surface.CalculateUV(newUV);
                        }
                        uvs[i] = newUV;

                        faceShape[i] = edgeShape[i].position;//used for triangulation
                        //                    normals[i] = normal;
                        tangents[i] = tangent;
                    }
//                    int[] tris = EarClipper.Triangulate(faceShape, 0, -1);
                    int[] tris     = Poly2TriWrapper.Triangulate(faceShape, true);
                    int   triCount = tris.Length;
                    if (triCount < 3)
                    {
                        continue;
                    }

                    Vector3 normal = BuildRMesh.CalculateNormal(verts[tris[0]], verts[tris[1]], verts[tris[2]]);
                    for (int i = 0; i < edgeShapeCount; i++)
                    {
                        normals[i] = normal;//normCal[i].normalized;
                    }
                    mesh.AddData(verts, uvs, tris, normals, tangents, submesh);

                    if (isGabled)
                    {
                        for (int t = 0; t < triCount; t += 3)
                        {
                            if (tris[t] == 0 || tris[t + 1] == 0 || tris[t + 2] == 0)
                            {
                                int beB = edgeShapeCount - 1;
                                if (tris[t] == beB || tris[t + 1] == beB || tris[t + 2] == beB)
                                {
                                    Vector3 b0       = verts[0];
                                    Vector3 b1       = verts[beB];
                                    int     topIndex = 0;
                                    for (int tx = 0; tx < 3; tx++)
                                    {
                                        if (tris[t + tx] != 0 && tris[t + tx] != beB)
                                        {
                                            topIndex = tris[t + tx];
                                        }
                                    }
                                    Vector3 b2 = verts[topIndex];

                                    Vector3 baseV = b1 - b0;
                                    Vector3 dir   = baseV.normalized;
                                    Vector3 face  = Vector3.Cross(Vector3.up, dir);
                                    //                                float length = baseV.magnitude;
                                    Vector3 center = Vector3.Lerp(b0, b1, 0.5f);
                                    Vector3 up     = Vector3.Project(b2 - b0, Vector3.up);
                                    Vector3 b3     = center + up;
                                    mesh.AddTri(b0, b2, b3, face, submesh);  //left
                                    mesh.AddTri(b1, b3, b2, -face, submesh); //right
                                    mesh.AddTri(b0, b3, b1, dir, submesh);   //face

                                    //clear triangle
                                    tris[t]     = 0;
                                    tris[t + 1] = 0;
                                    tris[t + 2] = 0;
                                }
                            }
                        }
                    }
                }
                else if (isFloor)
                {
                    Roof roof     = volume.roof;
                    Edge baseEdge = baseEdges[b];
                    Node nodeA    = baseEdge.nodeA;
                    Node nodeB    = baseEdge.nodeB;

                    Vector3 p0 = new Vector3(nodeA.position.x, heightScale + roofBaseHeight, nodeA.position.y);
                    Vector3 p1 = new Vector3(nodeB.position.x, heightScale + roofBaseHeight, nodeB.position.y);

                    Vector3 baseV = p1 - p0;
                    Vector3 dir   = baseV.normalized;
                    Vector3 face  = Vector3.Cross(Vector3.up, dir).normalized;

                    Vector3 parapetEdgeModifier = dir * (roof.overhang - (roof.parapetFrontDepth + roof.parapetBackDepth)) * 1.05f;
                    p0 += parapetEdgeModifier;
                    p1 += -parapetEdgeModifier;
//                    p0 += face * (roof.parapetFrontDepth + roof.parapetBackDepth + roof.overhang);

                    VolumePoint volumePoint = volume[facadeIndices[b]];
                    bool        simpleGable = volumePoint.simpleGable;
                    Gable       gableStyle  = volume[facadeIndices[b]].gableStyle;
                    if (!simpleGable && gableStyle == null)
                    {
                        simpleGable = true;
                    }
                    float thickness        = volume[facadeIndices[b]].gableThickness;
                    float additionalHeight = volume[facadeIndices[b]].gableHeight;
                    float height           = roof.height + additionalHeight;

                    if (simpleGable)                                                        //generate a simple gable
                    {
                        int wallSubmesh = mesh.submeshLibrary.SubmeshAdd(roof.wallSurface); //surfaceMapping.IndexOf(roof.wallSurface);
                        if (wallSubmesh == -1)
                        {
                            wallSubmesh = submesh;
                        }

                        Vector3 g0 = p0;
                        Vector3 g1 = p0 + Vector3.up * additionalHeight;
                        Vector3 g2 = g1 + dir * roof.floorDepth * 0.5f;
                        Vector3 g3 = g2 + dir * roof.depth * 0.5f + Vector3.up * roof.height;

                        Vector3 g7 = p1;
                        Vector3 g6 = p1 + Vector3.up * additionalHeight;
                        Vector3 g5 = g6 - dir * roof.floorDepth * 0.5f;
                        Vector3 g4 = g5 - dir * roof.depth * 0.5f + Vector3.up * roof.height;

                        Vector3 gF = -face * thickness;

                        mesh.AddPlane(g0, g7, g1, g6, wallSubmesh);                     //bottom front
                        mesh.AddPlane(g7 + gF, g0 + gF, g6 + gF, g1 + gF, wallSubmesh); //bottom back
                        mesh.AddPlane(g1, g6, g1 + gF, g6 + gF, wallSubmesh);           //bottom top
                        mesh.AddPlane(g0, g1, g0 + gF, g1 + gF, wallSubmesh);           //bottom sides
                        mesh.AddPlane(g6, g7, g6 + gF, g7 + gF, wallSubmesh);


                        mesh.AddPlane(g2, g5, g3, g4, wallSubmesh);                     //top front
                        mesh.AddPlane(g5 + gF, g2 + gF, g4 + gF, g3 + gF, wallSubmesh); //top back
                        mesh.AddPlane(g2 + gF, g2, g3 + gF, g3, wallSubmesh);           //top sides
                        mesh.AddPlane(g5, g5 + gF, g4, g4 + gF, wallSubmesh);           //top sides

                        mesh.AddPlane(g3 + gF, g3, g4 + gF, g4, wallSubmesh);           //top top
                    }
                    else
                    {
                        Vector2 baseUV = new Vector2(0, volume.planHeight);
                        GableGenerator.Generate(ref mesh, gableStyle, p0, p1, height, thickness, baseUV);
                    }
                }
            }

            if (generateDormers)
            {
                DormerGenerator.Generate(ref mesh, volume, roofFaces);
            }
        }