Beispiel #1
0
        private static Gable MenuCreateNewGableB()
        {
            Gable output = CreateGable();

            UnityEditor.Selection.activeObject = output;
            return(output);
        }
Beispiel #2
0
        public static Gable CreateGable()
        {
            Gable output = CreateInstance <Gable>();

#if UNITY_EDITOR
            UnityEditor.AssetDatabase.CreateAsset(output, AssetCreator.GeneratePath("newGable.asset", "Gables"));
            UnityEditor.AssetDatabase.SaveAssets();
            UnityEditor.AssetDatabase.Refresh();
#endif
            return(output);
        }
Beispiel #3
0
        public static void Generate(ref BuildRMesh mesh, Gable design, Vector3 p0, Vector3 p1, float height, float thickness, Vector2 baseUV)
        {
            int     gableSectionCount = design.count;
            Vector2 designSize        = new Vector2();

            for (int g = 0; g < gableSectionCount; g++)
            {
                designSize += design[g].GetSize();
            }
            Vector2 actualSize  = new Vector2(Vector3.Distance(p0, p1), height);
            Vector2 designScale = new Vector2((actualSize.x / 2) / designSize.x, actualSize.y / designSize.y);

            Vector2 basePosition    = Vector2.zero;
            Vector3 facadeVector    = p1 - p0;
            Vector3 facadeDirection = facadeVector.normalized;
            float   facadeWidth     = facadeVector.magnitude;
            Vector3 facadeNormal    = Vector3.Cross(Vector3.up, facadeDirection);

            Vector4 facadeTangentForward = BuildRMesh.CalculateTangent(facadeDirection);
            Vector4 facadeTangentLeft    = BuildRMesh.CalculateTangent(facadeNormal);
            Vector4 facadeTangentRight   = BuildRMesh.CalculateTangent(-facadeNormal);
            Vector4 facadeTangentBack    = BuildRMesh.CalculateTangent(-facadeDirection);

            Surface surface = design.surface;
            int     submesh = mesh.submeshLibrary.SubmeshAdd(surface);//surfaceMapping.IndexOf(surface);

            if (submesh == -1)
            {
                submesh = 0;
            }
            Vector3 back = -facadeNormal * thickness;

            for (int g = 0; g < gableSectionCount; g++)
            {
                float   sectionWidth = design[g].size.x * designScale.x;
                float   sectionHeight = design[g].size.y * designScale.y;
                Vector3 g0, g1, g2, g3;

                switch (design[g].type)
                {
                case GablePart.Types.Vertical:

                    g0 = p0 + facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    g1 = p1 - facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    g2 = g0 + Vector3.up * sectionHeight;
                    g3 = g1 + Vector3.up * sectionHeight;

                    Vector2 uvMax = baseUV + basePosition + new Vector2(facadeWidth - basePosition.x * 2, sectionHeight);
                    mesh.AddPlane(g0, g1, g2, g3, baseUV + basePosition, uvMax, facadeNormal, facadeTangentForward, submesh, surface);
                    Vector2 uvB0 = baseUV + basePosition + new Vector2(0, 0);
                    Vector2 uvB1 = baseUV + basePosition + new Vector2(facadeWidth - basePosition.x * 2, sectionHeight);
                    mesh.AddPlane(g1 + back, g0 + back, g3 + back, g2 + back, uvB0, uvB1, -facadeNormal, facadeTangentBack, submesh, surface);

                    var     gb0     = g0 + back;
                    var     gb1     = g1 + back;
                    var     gb2     = g2 + back;
                    var     gb3     = g3 + back;
                    Vector2 baseVUV = new Vector2(0, basePosition.y);
                    mesh.AddPlane(gb0, g0, gb2, g2, baseVUV, new Vector2(thickness, basePosition.y + sectionHeight), -facadeDirection, facadeTangentLeft, submesh, surface);
                    mesh.AddPlane(g1, gb1, g3, gb3, baseVUV, new Vector2(thickness, basePosition.y + sectionHeight), facadeDirection, facadeTangentRight, submesh, surface);

                    basePosition.y += sectionHeight;
                    break;

                case GablePart.Types.Horizonal:

                    g0 = p0 + facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    g1 = p1 - facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    g2 = g0 + facadeDirection * sectionWidth;
                    g3 = g1 - facadeDirection * sectionWidth;

                    Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection);
                    mesh.AddPlane(g0, g2, g0 + back, g2 + back, Vector3.zero, new Vector2(sectionWidth, thickness), Vector3.up, tangent, submesh, surface);
                    mesh.AddPlane(g3, g1, g3 + back, g1 + back, Vector3.zero, new Vector2(sectionWidth, thickness), Vector3.up, tangent, submesh, surface);

                    basePosition.x += sectionWidth;
                    break;

                case GablePart.Types.Diagonal:

                    Vector3 gd0 = p0 + facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    Vector3 gd1 = p1 - facadeDirection * basePosition.x + Vector3.up * basePosition.y;
                    Vector3 gd2 = gd0 + facadeDirection * sectionWidth + Vector3.up * sectionHeight;
                    Vector3 gd3 = gd1 - facadeDirection * sectionWidth + Vector3.up * sectionHeight;

                    Vector3 gdb0 = gd0 + back;
                    Vector3 gdb1 = gd1 + back;
                    Vector3 gdb2 = gd2 + back;
                    Vector3 gdb3 = gd3 + back;

                    Vector2 uv0 = baseUV + basePosition;
                    Vector2 uv1 = baseUV + new Vector2(basePosition.x + facadeWidth - basePosition.x * 2, basePosition.y);
                    Vector2 uv2 = baseUV + new Vector2(basePosition.x + sectionWidth, basePosition.y + sectionHeight);
                    Vector2 uv3 = baseUV + new Vector2(basePosition.x + facadeWidth - basePosition.x * 2 - sectionWidth, basePosition.y + sectionHeight);
                    mesh.AddPlaneComplex(gd0, gd1, gd2, gd3, uv0, uv1, uv2, uv3, facadeNormal, facadeTangentForward, submesh, surface);    //face
                    mesh.AddPlaneComplex(gdb1, gdb0, gdb3, gdb2, uv0, uv1, uv2, uv3, -facadeNormal, facadeTangentBack, submesh, surface);  //face

                    Vector3   leftNorm     = Vector3.Cross(-facadeNormal, (gd2 - gd0).normalized);
                    Vector3[] leftNorms    = { leftNorm, leftNorm, leftNorm, leftNorm };
                    Vector4   leftTangent  = facadeTangentLeft;
                    Vector4[] leftTangents = { leftTangent, leftTangent, leftTangent, leftTangent };

                    Vector3[] leftFace  = { gdb0, gd0, gdb2, gd2 };
                    float     faceWidth = Vector3.Distance(gd0, gd2);
                    Vector2   sideUV0   = Vector2.zero;
                    Vector2   sideUV1   = surface != null?surface.CalculateUV(new Vector2(thickness, 0)) : new Vector2(1, 0);

                    Vector2 sideUV2 = surface != null?surface.CalculateUV(new Vector2(0, faceWidth)) : new Vector2(0, 1);

                    Vector2 sideUV3 = surface != null?surface.CalculateUV(new Vector2(thickness, faceWidth)) : new Vector2(1, 1);

                    Vector2[] leftFaceUV = { sideUV0, sideUV1, sideUV2, sideUV3 };
                    mesh.AddData(leftFace, leftFaceUV, new[] { 0, 2, 1, 2, 3, 1 }, leftNorms, leftTangents, submesh);

                    Vector3   rightNorm     = Vector3.Cross(-facadeNormal, (gd1 - gd3).normalized);
                    Vector3[] rightNorms    = { rightNorm, rightNorm, rightNorm, rightNorm };
                    Vector4   rightTangent  = facadeTangentRight;
                    Vector4[] rightTangents = { rightTangent, rightTangent, rightTangent, rightTangent };

                    Vector3[] rightFace   = { gd1, gdb1, gd3, gdb3 };
                    Vector2[] rightFaceUV = { sideUV0, sideUV1, sideUV2, sideUV3 };    //todo
                    mesh.AddData(rightFace, rightFaceUV, new[] { 0, 2, 1, 2, 3, 1 }, rightNorms, rightTangents, submesh);

                    basePosition.x += sectionWidth;
                    basePosition.y += sectionHeight;
                    break;

                case GablePart.Types.Concave:

                    Arc(ref mesh, design, new Vector3(sectionWidth, sectionHeight, thickness), p0, p1, basePosition, submesh, surface, false, baseUV);

                    basePosition.x += sectionWidth;
                    basePosition.y += sectionHeight;
                    break;

                case GablePart.Types.Convex:

                    Arc(ref mesh, design, new Vector3(sectionWidth, sectionHeight, thickness), p0, p1, basePosition, submesh, surface, true, baseUV);

                    basePosition.x += sectionWidth;
                    basePosition.y += sectionHeight;
                    break;
                }
            }
        }
Beispiel #4
0
        private const float HPI = 1.570796f;//half PI
        private static void Arc(ref BuildRMesh mesh, Gable design, Vector3 sectorSize, Vector3 p0, Vector3 p1, Vector2 basePosition, int submesh, Surface surface, bool convex, Vector2 baseUV)
        {
            Vector3 facadeVector    = p1 - p0;
            Vector3 facadeDirection = facadeVector.normalized;
            float   facadeWidth     = facadeVector.magnitude;
            Vector3 facadeNormal    = Vector3.Cross(Vector3.up, facadeDirection);

            Vector4 facadeTangentForward = BuildRMesh.CalculateTangent(facadeDirection);
            Vector4 facadeTangentLeft    = BuildRMesh.CalculateTangent(facadeNormal);
            Vector4 facadeTangentRight   = BuildRMesh.CalculateTangent(-facadeNormal);
            Vector4 facadeTangentBack    = BuildRMesh.CalculateTangent(-facadeDirection);

            float sectionWidth  = sectorSize.x;
            float sectionHeight = sectorSize.y;
            float thickness     = sectorSize.z;

            var segmentCount = design.segments;
            var vertCount    = segmentCount * 8 + 4;
            var verts        = new Vector3[vertCount];
            var uvs          = new Vector2[vertCount];
            var normals      = new Vector3[vertCount];
            var tangents     = new Vector4[vertCount];
            int triPart      = 24;
            //+ 12 for central section (6 front, 6 back)
            int     triCount  = (segmentCount - 1) * triPart + 12;
            var     triangles = new int[triCount];
            Vector3 back      = -facadeNormal * thickness;

            float arcLength = HPI * Mathf.Sqrt(2 * Mathf.Pow(sectorSize.x, 2) + 2 * Mathf.Pow(sectorSize.y, 2)) / 2f;

            //front

            //left
            verts[0] = p0 + facadeDirection * (basePosition.x + sectionWidth) + Vector3.up * basePosition.y;
            Vector2 leftBaseUV = baseUV + new Vector2(basePosition.x + sectionWidth, basePosition.y);

            uvs[0] = surface != null?surface.CalculateUV(leftBaseUV) : new Vector2(0, 0);

            normals[0]  = facadeNormal;
            tangents[0] = facadeTangentForward;
            //right
            verts[1] = p1 - facadeDirection * (basePosition.x + sectionWidth) + Vector3.up * basePosition.y;
            Vector2 rightBaseUV = baseUV + new Vector2(basePosition.x + facadeWidth - basePosition.x * 2 - sectionWidth, basePosition.y);

            uvs[1] = surface != null?surface.CalculateUV(rightBaseUV) : new Vector2(1, 0);

            normals[1]  = facadeNormal;
            tangents[1] = facadeTangentForward;

            //back
            //left
            int endVertIndexLeft = vertCount - 2;

            verts[endVertIndexLeft]    = verts[0] + back;
            uvs[endVertIndexLeft]      = uvs[1];
            normals[endVertIndexLeft]  = -facadeNormal;
            tangents[endVertIndexLeft] = facadeTangentBack;
            //right
            int endVertIndexRight = vertCount - 1;

            verts[endVertIndexRight]    = verts[1] + back;
            uvs[endVertIndexRight]      = uvs[0];
            normals[endVertIndexRight]  = -facadeNormal;
            tangents[endVertIndexRight] = facadeTangentBack;

            for (int i = 0; i < segmentCount; i++)
            {
                float percent     = i / (segmentCount - 1f);
                float arcDistance = arcLength * percent;
                float arcPercent  = convex ? percent : (1 - percent) + 2;
                float x           = Mathf.Sin(arcPercent * HPI);
                float y           = Mathf.Cos(arcPercent * HPI);

                if (!convex)
                {
                    x = (x + 1);
                    y = (y + 1);
                }

                Vector3 arcLeft  = facadeDirection * (-x * sectionWidth) + Vector3.up * y * sectionHeight;
                Vector3 arcRight = facadeDirection * (x * sectionWidth) + Vector3.up * y * sectionHeight;
                Vector3 vertA    = verts[0] + arcLeft;
                Vector3 vertB    = vertA + back;
                Vector3 vertC    = verts[1] + arcRight;
                Vector3 vertD    = vertC + back;

                //left
                verts[i + 2] = vertA;                    //front
                verts[i + 2 + segmentCount]     = vertA; //front top
                verts[i + 2 + segmentCount * 2] = vertB; //back top
                verts[i + 2 + segmentCount * 3] = vertB; //back

                uvs[i + 2] = surface != null?surface.CalculateUV(leftBaseUV + new Vector2(-x *sectionWidth, y *sectionHeight)) : new Vector2(0, 0);

                uvs[i + 2 + segmentCount] = surface != null?surface.CalculateUV(new Vector2(thickness, arcDistance)) : new Vector2(1, 0);

                uvs[i + 2 + segmentCount * 2] = surface != null?surface.CalculateUV(new Vector2(0, arcDistance)) : new Vector2(0, 1);

                uvs[i + 2 + segmentCount * 3] = surface != null?surface.CalculateUV(rightBaseUV + new Vector2(x *sectionWidth, y *sectionHeight)) : new Vector2(1, 1);


                //right
                verts[i + 2 + segmentCount * 4] = vertC; //front
                verts[i + 2 + segmentCount * 5] = vertC; //front top
                verts[i + 2 + segmentCount * 6] = vertD; //back top
                verts[i + 2 + segmentCount * 7] = vertD; //back

                uvs[i + 2 + segmentCount * 4] = surface != null?surface.CalculateUV(rightBaseUV + new Vector2(x *sectionWidth, y *sectionHeight)) : new Vector2(0, 0);

                uvs[i + 2 + segmentCount * 5] = surface != null?surface.CalculateUV(new Vector2(0, arcDistance)) : new Vector2(1, 0);

                uvs[i + 2 + segmentCount * 6] = surface != null?surface.CalculateUV(new Vector2(thickness, arcDistance)) : new Vector2(0, 1);

                uvs[i + 2 + segmentCount * 7] = surface != null?surface.CalculateUV(leftBaseUV + new Vector2(-x *sectionWidth, y *sectionHeight)) : new Vector2(1, 1);

                if (i < segmentCount - 1)
                {
                    //left

                    //front
                    triangles[i * triPart]     = 0;
                    triangles[i * triPart + 1] = i + 3;
                    triangles[i * triPart + 2] = i + 2;

                    //top
                    triangles[i * triPart + 3] = i + segmentCount + 2;
                    triangles[i * triPart + 4] = i + segmentCount + 3;
                    triangles[i * triPart + 5] = i + segmentCount * 2 + 2;
                    triangles[i * triPart + 6] = i + segmentCount + 3;
                    triangles[i * triPart + 7] = i + segmentCount * 2 + 3;
                    triangles[i * triPart + 8] = i + segmentCount * 2 + 2;

                    //back
                    triangles[i * triPart + 9]  = endVertIndexLeft;
                    triangles[i * triPart + 10] = i + 2 + segmentCount * 3;
                    triangles[i * triPart + 11] = i + 3 + segmentCount * 3;

                    //right

                    //front
                    triangles[i * triPart + 12] = 1;
                    triangles[i * triPart + 13] = i + segmentCount * 4 + 2;
                    triangles[i * triPart + 14] = i + segmentCount * 4 + 3;

                    //top
                    triangles[i * triPart + 15] = i + segmentCount * 5 + 3;
                    triangles[i * triPart + 16] = i + segmentCount * 5 + 2;
                    triangles[i * triPart + 17] = i + segmentCount * 6 + 2;
                    triangles[i * triPart + 18] = i + segmentCount * 5 + 3;
                    triangles[i * triPart + 19] = i + segmentCount * 6 + 2;
                    triangles[i * triPart + 20] = i + segmentCount * 6 + 3;

                    //back
                    triangles[i * triPart + 21] = endVertIndexRight;
                    triangles[i * triPart + 22] = i + 3 + segmentCount * 7;
                    triangles[i * triPart + 23] = i + 2 + segmentCount * 7;
                }

                //left
                normals[i + 2]  = facadeNormal;
                tangents[i + 2] = facadeTangentForward;

                Vector3 upNormalLeft = Vector3.Slerp(-facadeDirection, Vector3.up, percent);

                normals[i + 2 + segmentCount]  = upNormalLeft;
                tangents[i + 2 + segmentCount] = facadeTangentLeft;

                normals[i + 2 + segmentCount * 2]  = upNormalLeft;
                tangents[i + 2 + segmentCount * 2] = facadeTangentLeft;

                normals[i + 2 + segmentCount * 3]  = -facadeNormal;
                tangents[i + 2 + segmentCount * 3] = facadeTangentBack;

                //right
                normals[i + 2 + segmentCount * 4]  = facadeNormal;
                tangents[i + 2 + segmentCount * 4] = facadeTangentForward;

                Vector3 upNormalRight = Vector3.Slerp(facadeDirection, Vector3.up, percent);

                normals[i + 2 + segmentCount * 5]  = upNormalRight;
                tangents[i + 2 + segmentCount * 5] = facadeTangentRight;

                normals[i + 2 + segmentCount * 6]  = upNormalRight;
                tangents[i + 2 + segmentCount * 6] = facadeTangentRight;

                normals[i + 2 + segmentCount * 7]  = -facadeNormal;
                tangents[i + 2 + segmentCount * 7] = facadeTangentBack;
            }

            //inter arc faces
            //front
            triangles[triCount - 12] = 1;
            triangles[triCount - 11] = 0;
            triangles[triCount - 10] = 2;
            triangles[triCount - 9]  = 1;
            triangles[triCount - 8]  = 2;
            triangles[triCount - 7]  = segmentCount * 4 + 2;
            //back
            triangles[triCount - 6] = endVertIndexLeft;
            triangles[triCount - 5] = endVertIndexRight;
            triangles[triCount - 4] = 2 + segmentCount * 3;
            triangles[triCount - 3] = 2 + segmentCount * 3;
            triangles[triCount - 2] = endVertIndexRight;
            triangles[triCount - 1] = segmentCount * 7 + 2;//1;


            mesh.AddData(verts, uvs, triangles, normals, tangents, submesh);
        }
Beispiel #5
0
        public static bool Generate(BuildRMesh mesh, BuildRCollider collider, Vector2[] points, int[] facadeIndices, float roofBaseHeight, IVolume volume, Rect clampUV)
        {
            Roof           design     = volume.roof;
            OffsetSkeleton offsetPoly = new OffsetSkeleton(points);

            offsetPoly.direction = 1;
            offsetPoly.Execute();
            Shape shape       = offsetPoly.shape;
            int   submesh     = mesh.submeshLibrary.SubmeshAdd(design.mainSurface); // surfaceMapping.IndexOf(design.mainSurface);
            int   wallSubmesh = mesh.submeshLibrary.SubmeshAdd(design.wallSurface); //surfaceMapping.IndexOf(design.wallSurface);

            if (shape == null)
            {
                return(false);
            }

            List <Edge> edges     = new List <Edge>(shape.edges);
            List <Edge> baseEdges = new List <Edge>(shape.baseEdges);

            float shapeHeight  = shape.HeighestPoint();
            float designHeight = design.height;
            float heightScale  = designHeight / shapeHeight;

            Vector2 clampUVScale = Vector2.one;

            if (clampUV.width > 0)
            {
                FlatBounds bounds = new FlatBounds();
                for (int fvc = 0; fvc < points.Length; fvc++)
                {
                    bounds.Encapsulate(points[fvc]);
                }
                clampUVScale.x = bounds.width / clampUV.width;
                clampUVScale.y = bounds.height / clampUV.height;
            }

            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;

            for (int b = 0; b < baseEdgeCount; b++)
            {
                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;
                        }
                        Vector2 nextDirection = (connectingNode.position - currentNode.position).normalized;
                        float   nodeAngle     = JMath.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 < 3)
                {
                    continue;
                }
//                Debug.Log("Generate edgeShapeCount "+ edgeShapeCount);

                Vector3[] verts = new Vector3[edgeShapeCount];

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

                Vector2[] faceShape = new Vector2[edgeShapeCount];
                Vector3[] normals   = new Vector3[edgeShapeCount];
                Vector4[] tangents  = new Vector4[edgeShapeCount];
                //                Vector3 normal = Vector3.up;//BuildRMesh.CalculateNormal(); TODO
                Vector4 tangent = BuildRMesh.CalculateTangent(baseShapeDirection);
                for (int i = 0; i < edgeShapeCount; i++)//what on earth did I write here?
                {
                    Vector3 newVert = new Vector3(edgeShape[i].position.x, edgeShape[i].height * heightScale + roofBaseHeight, edgeShape[i].position.y);
                    verts[i] = newVert;

                    Vector2 baseUV = new Vector2(newVert.x - verts[0].x, newVert.z - verts[0].z);
                    Vector2 newUV  = Vector2.zero;
                    if (i != 0)
                    {
                        newUV = JMath.Rotate(baseUV, uvAngle);
                    }
                    if (clampUV.width > Mathf.Epsilon)
                    {
                        newUV.x = Mathf.Clamp(clampUV.x + newUV.x / clampUVScale.x, clampUV.xMin, clampUV.xMax);
                        newUV.y = Mathf.Clamp(clampUV.y + newUV.y / clampUVScale.y, clampUV.yMin, clampUV.yMax);
                    }
                    else
                    {
                        if (i != 0)
                        {
                            float faceHeight = edgeShape[i].height * heightScale;
                            newUV.y = Mathf.Sqrt((newUV.y * newUV.y) + (faceHeight * faceHeight));//hypotenuse of roof to give length of roof face
                            if (design.mainSurface != null)
                            {
                                newUV = design.mainSurface.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;

                Vector3 normal = (verts.Length > 2 && triCount > 2) ? BuildRMesh.CalculateNormal(verts[tris[0]], verts[tris[1]], verts[tris[2]]) : Vector3.up;
                for (int i = 0; i < edgeShapeCount; i++)
                {
                    normals[i] = normal;
                }

                mesh.AddData(verts, uvs, tris, normals, tangents, submesh);

                //gable
                bool isGabled = volume[facadeIndices[b]].isGabled;
                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];
                                Vector3 g0       = b0;
                                Vector3 g1       = b1;
                                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).normalized;
                                Vector3 up    = Vector3.Project(b2 - b0, Vector3.up);

                                //clear triangle
                                tris[t]     = 0;
                                tris[t + 1] = 0;
                                tris[t + 2] = 0;

                                bool  simpleGable      = volume[facadeIndices[b]].simpleGable;
                                Gable gableStyle       = volume[facadeIndices[b]].gableStyle;
                                float thickness        = volume[facadeIndices[b]].gableThickness;
                                float additionalHeight = volume[facadeIndices[b]].gableHeight;
                                float height           = up.magnitude + additionalHeight;

                                if (simpleGable || gableStyle != null)
                                {
                                    Vector3 pitchVectorA = (b2 - b0).normalized;
                                    Vector3 pitchVectorB = (b2 - b1).normalized;
                                    float   angle        = Vector3.Angle(-face, pitchVectorA);
                                    float   scale        = Mathf.Cos(angle / 57.2957795f);
                                    b0 += pitchVectorA * (thickness * (1 / scale));
                                    b1 += pitchVectorB * (thickness * (1 / scale));
                                }

                                Vector3 center = Vector3.Lerp(b0, b1, 0.5f);
                                up = Vector3.Project(b2 - b0, Vector3.up); //recalculate after b change(?)
                                Vector3 b3 = center + up;
                                if (simpleGable)                           //generate a simple gable
                                {
                                    //generate simple gable based on roof
                                    Vector3 gCenter = Vector3.Lerp(g0, g1, 0.5f);
                                    Vector3 gBaseUp = Vector3.up * additionalHeight;
                                    Vector3 gUp     = up.normalized * height;
                                    Vector3 gBack   = -face * thickness;
                                    //todo further calculations
                                    //face
                                    mesh.AddPlane(g0, g1, g0 + gBaseUp, g1 + gBaseUp, wallSubmesh);
                                    mesh.AddTri(g1 + gBaseUp, g0 + gBaseUp, gCenter + gUp, dir, wallSubmesh);
                                    //backface
                                    mesh.AddPlane(g1 + gBack, g0 + gBack, g1 + gBaseUp + gBack, g0 + gBaseUp + gBack, wallSubmesh);
                                    mesh.AddTri(g0 + gBack + gBaseUp, g1 + gBack + gBaseUp, b3 + gBaseUp, -dir, wallSubmesh);
                                    //left
                                    mesh.AddPlane(g0 + gBack, g0, g0 + gBaseUp + gBack, g0 + gBaseUp, wallSubmesh);
                                    mesh.AddPlane(g0 + gBaseUp + gBack, g0 + gBaseUp, b3 + gBaseUp, gCenter + gUp, wallSubmesh);
                                    //right
                                    mesh.AddPlane(g1, g1 + gBack, g1 + gBaseUp, g1 + gBaseUp + gBack, wallSubmesh);
                                    mesh.AddPlane(g1 + gBaseUp, g1 + gBaseUp + gBack, gCenter + gUp, b3 + gBaseUp, wallSubmesh);
                                }
                                else if (volume[facadeIndices[b]].gableStyle != null)
                                {
                                    Vector2 baseUV = new Vector2(0, volume.planHeight);
                                    GableGenerator.Generate(ref mesh, gableStyle, g0, g1, height, thickness, baseUV);
                                }
                                else
                                {
                                    mesh.AddTri(b0, b3, b1, dir, submesh);//face - no separate gable
                                }

                                mesh.AddTri(b0, b2, b3, face, submesh);  //left
                                mesh.AddTri(b1, b3, b2, -face, submesh); //right
                            }
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #6
0
 private void OnEnable()
 {
     _gable = (Gable)target;
     _plane = Primitives.Plane(10);
     //            _blueprintMaterial = AssetDatabase.LoadAssetAtPath<Material>("Assets/BuildR2/Materials/Blueprint.mat");//TODO make independent of BuildR location
 }
        static void ItemOnGui(string guid, Rect rect)
        {
            if (settings == null)
            {
                settings = BuildRSettings.GetSettings();
            }
            if (!settings.iconPreviews)
            {
                return;
            }

            bool  defaultFound  = settings.defaultIcon != null;
            Rect  squareRect    = new Rect(rect.x, rect.y, rect.height, rect.height);
            float defaultHeight = Mathf.Min(56, rect.height);
            float defaultWidth  = Mathf.Min(44, rect.width, defaultHeight * 0.7857f);
            float defaultX      = rect.x;
            float defaultY      = rect.y;

            if (rect.height > 56)
            {
                defaultX = rect.x + (rect.width - 44) * 0.5f;
                defaultY = rect.y + (rect.height - 70) * 0.5f;
            }
            Rect defaultRect = new Rect(defaultX, defaultY, defaultWidth, defaultHeight);

//            IconUtil.GUIDIconData iconData = settings.GetCustomIconData(guid);
//            if(iconData == null)
//            {
//                iconData = IconUtil.GenerateGUIDIconData(guid);
//                settings.AddCustomIconData(guid, iconData);
//            }

            string      assetPath   = AssetDatabase.GUIDToAssetPath(guid);
            WallSection wallSection = AssetDatabase.LoadAssetAtPath(assetPath, typeof(WallSection)) as WallSection;

            if (wallSection != null)
            {
                Texture2D wallSectionPreview = wallSection.previewTexture;
                if (wallSectionPreview != null)
                {
                    GUI.DrawTexture(squareRect, wallSectionPreview);
                }
                else if (defaultFound)
                {
                    GUI.DrawTexture(defaultRect, settings.defaultIcon);
                }
            }


            Facade facade = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Facade)) as Facade;

            if (facade != null)
            {
                Texture2D facadePreview = facade.previewTexture;
                if (facadePreview != null)
                {
                    GUI.DrawTexture(squareRect, facadePreview);
                }
                else if (defaultFound)
                {
                    GUI.DrawTexture(defaultRect, settings.defaultIcon);
                }
            }

            Surface surface = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Surface)) as Surface;

            if (surface != null && surface.previewTexture != null)
            {
                if (surface.previewTexture != null)
                {
                    GUI.DrawTexture(squareRect, surface.previewTexture);
                }
                else if (defaultFound)
                {
                    GUI.DrawTexture(defaultRect, settings.defaultIcon);
                }
            }

            Gable gable = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Gable)) as Gable;

            if (defaultFound && gable != null)
            {
                GUI.DrawTexture(defaultRect, settings.defaultIcon);
            }

            RoomStyle roomStyle = AssetDatabase.LoadAssetAtPath(assetPath, typeof(RoomStyle)) as RoomStyle;

            if (defaultFound && roomStyle != null)
            {
                GUI.DrawTexture(defaultRect, settings.defaultIcon);
            }

            Portal portal = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Portal)) as Portal;

            if (defaultFound && portal != null)
            {
                GUI.DrawTexture(defaultRect, settings.defaultIcon);
            }

            BuildRSettings settingsIcon = AssetDatabase.LoadAssetAtPath(assetPath, typeof(BuildRSettings)) as BuildRSettings;

            if (defaultFound && settingsIcon != null)
            {
                GUI.DrawTexture(defaultRect, settings.defaultIcon);
            }
        }
Beispiel #8
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);
            }
        }