Example #1
0
        private static void ToMesh(ref BuildRMesh mesh, Vector2[] points, float height, int[] facadeIndices, IVolume volume, int submesh, Surface surface)
        {
            int vertCount = points.Length;

            Vector3[] verts = new Vector3[vertCount];
            for (int i = 0; i < vertCount; i++)
            {
                verts[i] = new Vector3(points[i].x, height, points[i].y);
            }
            Vector2[] uvs      = new Vector2[vertCount];
            Vector3[] normals  = new Vector3[vertCount];
            Vector4[] tangents = new Vector4[vertCount];
            Vector4   tangent  = BuildRMesh.CalculateTangent(Vector3.right);

            for (int v = 0; v < vertCount; v++)
            {
                if (surface != null)
                {
                    uvs[v] = surface.CalculateUV(points[v]);
                }
                normals[v]  = Vector3.up;
                tangents[v] = tangent;
            }

//            int[] topTris = EarClipper.Triangulate(points);
            int[] topTris = Poly2TriWrapper.Triangulate(points, true);
            mesh.AddData(verts, uvs, topTris, normals, tangents, submesh);
        }
Example #2
0
 private static Vector2 CalculateUv(Vector2 uv, Surface surface)
 {
     if (surface != null)
     {
         return(surface.CalculateUV(uv));
     }
     return(uv);
 }
Example #3
0
 private static Vector2 CalculateUV(Surface surface, Vector2 uv)
 {
     if (surface == null)
     {
         return(uv);
     }
     return(surface.CalculateUV(uv));
 }
Example #4
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;
                }
            }
        }
Example #5
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);
        }
Example #6
0
        public static void Generate(Chimney chimney, GenerationOutput output, SubmeshLibrary submeshLibrary = null)
        {
            RGEN.seed = chimney.seed;
            DYNAMIC_MESH.Clear();
            if (submeshLibrary != null)
            {
                DYNAMIC_MESH.submeshLibrary.AddRange(submeshLibrary.SURFACES.ToArray()); //DYNAMIC_MESH.submeshLibrary.Inject(ref submeshLibrary);
            }
            else
            {
                DYNAMIC_MESH.submeshLibrary.Add(chimney);
            }

            submeshLibrary = DYNAMIC_MESH.submeshLibrary;

            //CASE
            Vector3 caseNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange());
            Vector3 cs0             = new Vector3(-chimney.caseSize.x * 0.5f, 0, -chimney.caseSize.z * 0.5f);
            Vector3 cs1             = new Vector3(chimney.caseSize.x * 0.5f, 0, -chimney.caseSize.z * 0.5f);
            Vector3 cs2             = new Vector3(-chimney.caseSize.x * 0.5f, 0, chimney.caseSize.z * 0.5f);
            Vector3 cs3             = new Vector3(chimney.caseSize.x * 0.5f, 0, chimney.caseSize.z * 0.5f);

            Vector3 cs4 = new Vector3(-chimney.caseSize.x * 0.5f, chimney.caseSize.y, -chimney.caseSize.z * 0.5f) + caseNoiseVector;
            Vector3 cs5 = new Vector3(chimney.caseSize.x * 0.5f, chimney.caseSize.y, -chimney.caseSize.z * 0.5f) + caseNoiseVector;
            Vector3 cs6 = new Vector3(-chimney.caseSize.x * 0.5f, chimney.caseSize.y, chimney.caseSize.z * 0.5f) + caseNoiseVector;
            Vector3 cs7 = new Vector3(chimney.caseSize.x * 0.5f, chimney.caseSize.y, chimney.caseSize.z * 0.5f) + caseNoiseVector;

            Vector2 csuv0 = new Vector2(0, 0);
            Vector2 csuv1 = new Vector2(chimney.caseSize.x, chimney.caseSize.y);
            Vector2 csuv2 = new Vector2(csuv1.x, 0);
            Vector2 csuv3 = new Vector2(csuv1.x + chimney.caseSize.z, chimney.caseSize.y);
            Vector2 csuv4 = new Vector2(csuv3.x, 0);
            Vector2 csuv5 = new Vector2(csuv3.x + chimney.caseSize.x, chimney.caseSize.y);
            Vector2 csuv6 = new Vector2(csuv5.x, 0);
            Vector2 csuv7 = new Vector2(csuv5.x + chimney.caseSize.z, chimney.caseSize.y);
            Vector2 csuv8 = new Vector2(0, 0);
            Vector2 csuv9 = new Vector2(chimney.caseSize.x, chimney.caseSize.z);

            Vector4 cst0 = new Vector4(0, 0, 1, 0);
            Vector4 cst1 = new Vector4(1, 0, 1, 0);
            Vector4 cst2 = new Vector4(0, 0, -1, 0);
            Vector4 cst3 = new Vector4(-1, 0, 0, 0);
            Vector4 cst4 = new Vector4(0, 0, 1, 0);

            int caseSubmesh = submeshLibrary.SubmeshAdd(chimney.caseSurface);

            //sides
            DYNAMIC_MESH.AddPlane(cs0, cs1, cs4, cs5, csuv0, csuv1, Vector3.back, cst0, caseSubmesh, chimney.caseSurface);
            DYNAMIC_MESH.AddPlane(cs1, cs3, cs5, cs7, csuv2, csuv3, Vector3.right, cst1, caseSubmesh, chimney.caseSurface);
            DYNAMIC_MESH.AddPlane(cs3, cs2, cs7, cs6, csuv4, csuv5, Vector3.forward, cst2, caseSubmesh, chimney.caseSurface);
            DYNAMIC_MESH.AddPlane(cs2, cs0, cs6, cs4, csuv6, csuv7, Vector3.left, cst3, caseSubmesh, chimney.caseSurface);
            //top
            DYNAMIC_MESH.AddPlane(cs4, cs5, cs6, cs7, csuv8, csuv9, Vector3.up, cst4, caseSubmesh, chimney.caseSurface);//todo calculate the values for this - don't be lazy

            //CROWN
            Vector3 crownBase        = caseNoiseVector + Vector3.up * chimney.caseSize.y;
            Vector3 crownNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange());
            Vector3 cr0 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, 0, -chimney.crownSize.z * 0.5f);
            Vector3 cr1 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, 0, -chimney.crownSize.z * 0.5f);
            Vector3 cr2 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, 0, chimney.crownSize.z * 0.5f);
            Vector3 cr3 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, 0, chimney.crownSize.z * 0.5f);

            Vector3 cr4 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, chimney.crownSize.y, -chimney.crownSize.z * 0.5f) + crownNoiseVector;
            Vector3 cr5 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, chimney.crownSize.y, -chimney.crownSize.z * 0.5f) + crownNoiseVector;
            Vector3 cr6 = crownBase + new Vector3(-chimney.crownSize.x * 0.5f, chimney.crownSize.y, chimney.crownSize.z * 0.5f) + crownNoiseVector;
            Vector3 cr7 = crownBase + new Vector3(chimney.crownSize.x * 0.5f, chimney.crownSize.y, chimney.crownSize.z * 0.5f) + crownNoiseVector;

            Vector2 cruv0 = new Vector2(0, 0);
            Vector2 cruv1 = new Vector2(chimney.crownSize.x, chimney.crownSize.y);
            Vector2 cruv2 = new Vector2(csuv1.x, 0);
            Vector2 cruv3 = new Vector2(csuv1.x + chimney.caseSize.z, chimney.crownSize.y);
            Vector2 cruv4 = new Vector2(csuv3.x, 0);
            Vector2 cruv5 = new Vector2(csuv3.x + chimney.crownSize.x, chimney.crownSize.y);
            Vector2 cruv6 = new Vector2(csuv5.x, chimney.crownSize.y);
            Vector2 cruv7 = new Vector2(csuv5.x + chimney.crownSize.z, chimney.crownSize.y);
            Vector2 cruv8 = new Vector2(0, 0);
            Vector2 cruv9 = new Vector2(chimney.crownSize.x, chimney.crownSize.z);

            Vector4 crt0 = new Vector4(0, 0, 1, 0);
            Vector4 crt1 = new Vector4(1, 0, 1, 0);
            Vector4 crt2 = new Vector4(0, 0, -1, 0);
            Vector4 crt3 = new Vector4(-1, 0, 0, 0);
            Vector4 crt4 = new Vector4(0, 0, 1, 0);

            int crownSubmesh = submeshLibrary.SubmeshAdd(chimney.crownSurface);

            DYNAMIC_MESH.AddPlane(cr0, cr1, cr4, cr5, cruv0, cruv1, Vector3.back, crt0, crownSubmesh, chimney.crownSurface);    //todo calculate the values for this - don't be lazy
            DYNAMIC_MESH.AddPlane(cr1, cr3, cr5, cr7, cruv2, cruv3, Vector3.right, crt1, crownSubmesh, chimney.crownSurface);   //todo calculate the values for this - don't be lazy
            DYNAMIC_MESH.AddPlane(cr3, cr2, cr7, cr6, cruv4, cruv5, Vector3.forward, crt2, crownSubmesh, chimney.crownSurface); //todo calculate the values for this - don't be lazy
            DYNAMIC_MESH.AddPlane(cr2, cr0, cr6, cr4, cruv6, cruv7, Vector3.left, crt3, crownSubmesh, chimney.crownSurface);    //todo calculate the values for this - don't be lazy
            DYNAMIC_MESH.AddPlane(cr1, cr0, cr3, cr2, cruv8, cruv9, Vector3.down, crt4, crownSubmesh, chimney.crownSurface);    //todo calculate the values for this - don't be lazy
            DYNAMIC_MESH.AddPlane(cr4, cr5, cr6, cr7, cruv8, cruv9, Vector3.up, crt4, crownSubmesh, chimney.crownSurface);      //todo calculate the values for this - don't be lazy

            int xCount = 1;
            int zCount = 1;

            if (chimney.allowMultiple)
            {
                xCount = Mathf.FloorToInt((chimney.crownSize.x - chimney.flueSpacing) / (chimney.flueSize.x + chimney.flueSpacing));
                if (xCount < 1)
                {
                    xCount = 1;
                }
                if (chimney.allowMultipleRows)
                {
                    zCount = Mathf.FloorToInt((chimney.crownSize.z - chimney.flueSpacing) / (chimney.flueSize.z + chimney.flueSpacing));
                    if (zCount < 1)
                    {
                        zCount = 1;
                    }
                }
            }

            float xSpacing = (chimney.crownSize.x - chimney.flueSize.x * xCount) / (xCount + 1);
            float zSpacing = (chimney.crownSize.z - chimney.flueSize.z * zCount) / (zCount + 1);

            //FLUES
            for (int x = 0; x < xCount; x++)
            {
                for (int z = 0; z < zCount; z++)
                {
                    Vector3 flueBase = cr4 + new Vector3(xSpacing + x * (chimney.flueSize.x + xSpacing) + chimney.flueSize.x * 0.5f, 0, zSpacing + z * (chimney.flueSize.z + zSpacing) + chimney.flueSize.z * 0.5f);

                    float   thickness  = (chimney.flueSize.x + chimney.flueSize.z) * 0.05f;//10%
                    float   drop       = chimney.flueSize.y * 0.9f;
                    Vector4 topTangent = new Vector4(1, 0, 0, 0);

                    Surface useFlueSurface = GenerationUtil.GetSurface(chimney.flueSurfaces, RGEN);
                    int     flueSubmesh    = submeshLibrary.SubmeshAdd(useFlueSurface);
                    int     innerSubmesh   = submeshLibrary.SubmeshAdd(chimney.innerSurface);

                    Vector3 flueNoiseVector = new Vector3(chimney.noise.x * RGEN.OneRange(), chimney.noise.y * RGEN.OneRange(), chimney.noise.z * RGEN.OneRange());

                    if (chimney.square)
                    {
                        Vector3 f0 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, 0, -chimney.flueSize.z * 0.5f);
                        Vector3 f1 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, 0, -chimney.flueSize.z * 0.5f);
                        Vector3 f2 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, 0, chimney.flueSize.z * 0.5f);
                        Vector3 f3 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, 0, chimney.flueSize.z * 0.5f);

                        Vector3 f4 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, chimney.flueSize.y, -chimney.flueSize.z * 0.5f) + flueNoiseVector;
                        Vector3 f5 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, chimney.flueSize.y, -chimney.flueSize.z * 0.5f) + flueNoiseVector;
                        Vector3 f6 = flueBase + new Vector3(-chimney.flueSize.x * 0.5f, chimney.flueSize.y, chimney.flueSize.z * 0.5f) + flueNoiseVector;
                        Vector3 f7 = flueBase + new Vector3(chimney.flueSize.x * 0.5f, chimney.flueSize.y, chimney.flueSize.z * 0.5f) + flueNoiseVector;

                        Vector3 f4i = f4 + new Vector3(thickness, 0, thickness) + flueNoiseVector;
                        Vector3 f5i = f5 + new Vector3(-thickness, 0, thickness) + flueNoiseVector;
                        Vector3 f6i = f6 + new Vector3(thickness, 0, -thickness) + flueNoiseVector;
                        Vector3 f7i = f7 + new Vector3(-thickness, 0, -thickness) + flueNoiseVector;

                        Vector3 f4id = f4i + new Vector3(0, -drop, 0);
                        Vector3 f5id = f5i + new Vector3(0, -drop, 0);
                        Vector3 f6id = f6i + new Vector3(0, -drop, 0);
                        Vector3 f7id = f7i + new Vector3(0, -drop, 0);

//            Vector2 fuv0 = new Vector2(0, 0);
//            Vector2 fuv1 = new Vector2(chimney.flueSize.x, 0);
//            Vector2 fuv2 = new Vector2(fuv1.x + chimney.flueSize.z, 0);
//            Vector2 fuv3 = new Vector2(fuv2.x + chimney.flueSize.x, 0);
//
//            Vector2 fuv4 = new Vector2(0, chimney.flueSize.y);
//            Vector2 fuv5 = new Vector2(chimney.flueSize.x, chimney.flueSize.y);
//            Vector2 fuv6 = new Vector2(fuv1.x + chimney.flueSize.z, chimney.flueSize.y);
//            Vector2 fuv7 = new Vector2(fuv2.x + chimney.flueSize.x, chimney.flueSize.y);


                        //Flue Sides
                        DYNAMIC_MESH.AddPlane(f0, f1, f4, f5, flueSubmesh);                                                  //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f1, f3, f5, f7, flueSubmesh);                                                  //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f3, f2, f7, f6, flueSubmesh);                                                  //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f2, f0, f6, f4, flueSubmesh);                                                  //todo calculate the values for this - don't be lazy
                                                                                                                             //Flue Top
                        DYNAMIC_MESH.AddPlaneComplex(f4, f5, f4i, f5i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlaneComplex(f5, f7, f5i, f7i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlaneComplex(f7, f6, f7i, f6i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlaneComplex(f6, f4, f6i, f4i, Vector3.up, topTangent, flueSubmesh, useFlueSurface); //todo calculate the values for this - don't be lazy
                                                                                                                             //Flue Drop
                        DYNAMIC_MESH.AddPlane(f5id, f4id, f5i, f4i, innerSubmesh);                                           //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f7id, f5id, f7i, f5i, innerSubmesh);                                           //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f6id, f7id, f6i, f7i, innerSubmesh);                                           //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f4id, f6id, f4i, f6i, innerSubmesh);                                           //todo calculate the values for this - don't be lazy
                        DYNAMIC_MESH.AddPlane(f4id, f5id, f6id, f7id, innerSubmesh);                                         //todo calculate the values for this - don't be lazy
                    }
                    else
                    {
                        int         vertCount = (chimney.segments + 1) * 2;//add an additonal so we can wrap the UVs well
                        RawMeshData flueOuter = new RawMeshData(vertCount, chimney.segments * 6);
                        RawMeshData flueTop   = new RawMeshData(vertCount, chimney.segments * 6);
                        //add additional point for the middle, bottom of the inside of the flue
                        RawMeshData flueInner = new RawMeshData(vertCount + 1, chimney.segments * 9);

                        //the additonal point at the bottom of the flue - added to the end of the mesh data
                        flueInner.vertices[vertCount] = flueBase;
                        flueInner.normals[vertCount]  = Vector3.up;
                        flueInner.tangents[vertCount] = new Vector4(1, 0, 0, 0);
                        int   indexIm       = flueInner.vertCount - 1;
                        float circumference = Mathf.PI * (chimney.flueSize.x + chimney.flueSize.z);

                        for (int s = 0; s < chimney.segments + 1; s++)
                        {
                            float percent = s / (float)(chimney.segments);
                            percent = (percent + (chimney.angleOffset / 360)) % 1f;

                            int indexV0 = s * 2;
                            int indexV1 = s * 2 + 1;
                            int indexV2 = s * 2 + 2;
                            int indexV3 = s * 2 + 3;
                            if (s == chimney.segments - 1)
                            {
                                indexV2 = 0;
                                indexV3 = 1;
                            }

                            float xa = Mathf.Sin(percent * Mathf.PI * 2) * chimney.flueSize.x * 0.5f;
                            float za = Mathf.Cos(percent * Mathf.PI * 2) * chimney.flueSize.z * 0.5f;
//              float innerHalf = thickness / (chimney.flueSize.x + chimney.flueSize.z) / 2;
                            float xai = Mathf.Sin(percent * Mathf.PI * 2) * chimney.flueSize.x * 0.4f;
                            float zai = Mathf.Cos(percent * Mathf.PI * 2) * chimney.flueSize.z * 0.4f;

                            Vector3 v0 = flueBase + new Vector3(xa, 0, za);
                            Vector3 v1 = flueBase + new Vector3(xa, chimney.flueSize.y, za) + flueNoiseVector;
                            Vector3 v2 = flueBase + new Vector3(xai, chimney.flueSize.y, zai) + flueNoiseVector;
                            Vector3 v3 = flueBase + new Vector3(xai, chimney.flueSize.y * 0.1f, zai);

                            Vector2 uv0 = new Vector2(-circumference * percent, 0);
                            Vector2 uv1 = new Vector2(-circumference * percent, chimney.flueSize.y);
                            Vector2 uv2 = new Vector2(-circumference * percent, chimney.flueSize.y + 0.1f);
                            Vector2 uv3 = new Vector2(-circumference * percent, 0);

                            int     rdnFlueSurfaceIndex = RGEN.Index(chimney.flueSurfaces.Count);
                            Surface flueSurface         = rdnFlueSurfaceIndex != -1 ? chimney.flueSurfaces[rdnFlueSurfaceIndex] : null;


                            if (flueSurface != null)
                            {
                                uv0 = flueSurface.CalculateUV(uv0);
                                uv1 = flueSurface.CalculateUV(uv1);
                                uv2 = flueSurface.CalculateUV(uv2);
                                uv3 = flueSurface.CalculateUV(uv3);
                            }

                            flueOuter.vertices[indexV0] = v0;
                            flueOuter.vertices[indexV1] = v1;
                            flueOuter.uvs[indexV0]      = uv0;
                            flueOuter.uvs[indexV1]      = uv1;

                            flueTop.vertices[indexV0] = v1;
                            flueTop.vertices[indexV1] = v2;
                            flueTop.uvs[indexV0]      = uv1;
                            flueTop.uvs[indexV1]      = uv2;

                            flueInner.vertices[indexV0] = v2;
                            flueInner.vertices[indexV1] = v3;
                            flueInner.uvs[indexV0]      = uv2;
                            flueInner.uvs[indexV1]      = uv3;

                            Vector3 outerNormal = new Vector3(Mathf.Sin(percent * Mathf.PI * 2), 0, Mathf.Cos(percent * Mathf.PI * 2));
                            flueOuter.normals[indexV0] = outerNormal;
                            flueOuter.normals[indexV1] = outerNormal;
                            flueTop.normals[indexV0]   = Vector3.up;
                            flueTop.normals[indexV1]   = Vector3.up;
                            flueInner.normals[indexV0] = -outerNormal;
                            flueInner.normals[indexV1] = -outerNormal;

                            if (s < chimney.segments)
                            {
                                int tidx0 = s * 6;
                                flueOuter.triangles[tidx0 + 0] = indexV0;
                                flueOuter.triangles[tidx0 + 2] = indexV1;
                                flueOuter.triangles[tidx0 + 1] = indexV2;
                                flueOuter.triangles[tidx0 + 3] = indexV1;
                                flueOuter.triangles[tidx0 + 4] = indexV2;
                                flueOuter.triangles[tidx0 + 5] = indexV3;

                                flueTop.triangles[tidx0 + 0] = indexV0;
                                flueTop.triangles[tidx0 + 2] = indexV1;
                                flueTop.triangles[tidx0 + 1] = indexV2;
                                flueTop.triangles[tidx0 + 3] = indexV1;
                                flueTop.triangles[tidx0 + 4] = indexV2;
                                flueTop.triangles[tidx0 + 5] = indexV3;

                                int tidx0i = s * 9;
                                flueInner.triangles[tidx0i + 0] = indexV0;
                                flueInner.triangles[tidx0i + 2] = indexV1;
                                flueInner.triangles[tidx0i + 1] = indexV2;
                                flueInner.triangles[tidx0i + 3] = indexV1;
                                flueInner.triangles[tidx0i + 4] = indexV2;
                                flueInner.triangles[tidx0i + 5] = indexV3;

                                flueInner.triangles[tidx0i + 6] = indexV1;
                                flueInner.triangles[tidx0i + 7] = indexV3;
                                flueInner.triangles[tidx0i + 8] = indexIm;
                            }
                        }

                        DYNAMIC_MESH.AddData(flueOuter, flueSubmesh);
                        DYNAMIC_MESH.AddData(flueTop, flueSubmesh);
                        DYNAMIC_MESH.AddData(flueInner, innerSubmesh);
                    }
                }
            }


            if (output.raw != null)
            {
                output.raw.Copy(DYNAMIC_MESH);
            }

            if (output.mesh != null)
            {
                output.mesh.Clear(false);
                DYNAMIC_MESH.Build(output.mesh);
            }
        }
Example #7
0
        public static void Generate(IBuilding building, IVolume volume, IFloorplan floorplan, int volumeFloor, VerticalOpening[] openings, BuildRMesh mesh, BuildRCollider collider)
        {
            SubmeshLibrary submeshLibrary = mesh.submeshLibrary;

            bool           generateColliders     = building.colliderType != BuildingColliderTypes.None;
            bool           generateMeshColliders = building.colliderType != BuildingColliderTypes.Primitive && generateColliders;
            BuildRCollider sendCollider          = (generateColliders) ? collider : null;

            collider.thickness = volume.wallThickness;
            if (!generateMeshColliders)
            {
                collider = null;
            }

            float   wallThickness = volume.wallThickness;
            float   wallUp        = volume.floorHeight - wallThickness;
            Vector3 wallUpV       = Vector3.up * wallUp;
            Vector3 floorBaseV    = Vector3.up * volume.baseHeight;

            int roomCount = floorplan.RoomCount;

            int actualFloor  = building.VolumeBaseFloor(volume) + volumeFloor;
            int openingCount = openings.Length;

            bool[]       openingBelow           = new bool[openingCount];
            bool[]       openingAbove           = new bool[openingCount];
            FlatBounds[] openingBounds          = new FlatBounds[openingCount];
            Vector2[][]  openingShapes          = new Vector2[openingCount][];
            bool[]       openingUsedInThisFloor = new bool[openingCount];
            for (int o = 0; o < openingCount; o++)
            {
                VerticalOpening opening = openings[o];
                if (!openings[o].FloorIsIncluded(actualFloor))
                {
                    continue;
                }
                openingBelow[o]  = opening.FloorIsIncluded(actualFloor - 1);
                openingAbove[o]  = opening.FloorIsIncluded(actualFloor + 1);
                openingShapes[o] = opening.PointsRotated();
                openingBounds[o] = new FlatBounds(openingShapes[o]);

                submeshLibrary.Add(opening.surfaceA);
                submeshLibrary.Add(opening.surfaceB);
                submeshLibrary.Add(opening.surfaceC);
                submeshLibrary.Add(opening.surfaceD);
            }

            Dictionary <int, List <Vector2Int> > externalWallAnchors = volume.facadeWallAnchors;

            Room[] rooms = floorplan.AllRooms();
            for (int r = 0; r < roomCount; r++)
            {
                Room room       = rooms[r];
                int  pointCount = room.numberOfPoints;

                Surface floorSurface   = null;
                Surface wallSurface    = null;
                Surface ceilingSurface = null;

                if (room.style != null)
                {
                    RoomStyle style = room.style;
                    floorSurface   = style.floorSurface;
                    wallSurface    = style.wallSurface;
                    ceilingSurface = style.ceilingSurface;
                }

                int floorSubmesh   = submeshLibrary.SubmeshAdd(floorSurface);
                int wallSubmesh    = submeshLibrary.SubmeshAdd(wallSurface);
                int ceilingSubmesh = submeshLibrary.SubmeshAdd(ceilingSurface);

                FloorplanUtil.RoomWall[] walls = FloorplanUtil.CalculatePoints(room, volume);
                Vector2[] roomArchorPoints     = FloorplanUtil.RoomArchorPoints(walls);

                Vector4 tangent = BuildRMesh.CalculateTangent(Vector3.right);

                Vector2[] offsetRoomAnchorPoints = QuickPolyOffset.Execute(roomArchorPoints, wallThickness);

                FlatBounds             roomBounds   = new FlatBounds(offsetRoomAnchorPoints);
                List <Vector2[]>       floorCuts    = new List <Vector2[]>();
                List <Vector2[]>       ceilingCuts  = new List <Vector2[]>();
                List <VerticalOpening> roomOpenings = new List <VerticalOpening>();
                for (int o = 0; o < openingCount; o++)
                {
                    if (openings[o].FloorIsIncluded(actualFloor))
                    {
                        if (roomBounds.Overlaps(openingBounds[o]))
                        {
                            if (CheckShapeWithinRoom(offsetRoomAnchorPoints, openingShapes[o]))
                            {
                                if (openingBelow[o])
                                {
                                    floorCuts.Add(openingShapes[o]);
                                }
                                if (openingAbove[o])
                                {
                                    ceilingCuts.Add(openingShapes[o]);
                                }
                                if (openingAbove[o] || openingBelow[o])
                                {
                                    roomOpenings.Add(openings[o]);
                                    openingUsedInThisFloor[o] = true;
                                }
                            }
                        }
                    }
                }

                int offsetPointBase = 0;
                for (int p = 0; p < pointCount; p++)//generate room walls
                {
                    FloorplanUtil.RoomWall wall = walls[p];
                    int wallPointCount          = wall.offsetPoints.Length;

                    List <RoomPortal> wallPortals = floorplan.GetWallPortals(room, p);
                    int wallPortalCount           = wallPortals.Count;

                    if (!wall.isExternal)
                    {
                        int     indexA    = offsetPointBase;
                        int     indexB    = (offsetPointBase + 1) % roomArchorPoints.Length;
                        Vector2 origBaseA = roomArchorPoints[indexA];
                        Vector2 origBaseB = roomArchorPoints[indexB];
                        Vector2 baseA     = offsetRoomAnchorPoints[indexA];
                        Vector2 baseB     = offsetRoomAnchorPoints[indexB];
                        Vector3 v0        = new Vector3(origBaseA.x, 0, origBaseA.y) + floorBaseV;
                        Vector3 v1        = new Vector3(origBaseB.x, 0, origBaseB.y) + floorBaseV;
                        Vector3 vOffset0  = new Vector3(baseA.x, 0, baseA.y) + floorBaseV;
                        Vector3 vOffset1  = new Vector3(baseB.x, 0, baseB.y) + floorBaseV;
                        if (wallPortalCount == 0)  //just draw the wall - no portals to cut

                        {
                            Vector3 v2 = vOffset1 + wallUpV;
                            Vector3 v3 = vOffset0 + wallUpV;

                            Vector2 minUV = Vector2.zero;
                            Vector2 maxUV = new Vector2(Vector2.Distance(baseA, baseB), wallUp);
                            if (wallSurface != null)
                            {
                                maxUV = wallSurface.CalculateUV(maxUV);
                            }
                            Vector3 wallDir     = (vOffset0 - vOffset1).normalized;
                            Vector3 wallNormal  = Vector3.Cross(Vector3.up, wallDir);
                            Vector4 wallTangent = BuildRMesh.CalculateTangent(wallDir);
                            mesh.AddPlane(vOffset1, vOffset0, v2, v3, minUV, maxUV, wallNormal, wallTangent, wallSubmesh, wallSurface);

                            if (generateColliders)
                            {
                                collider.AddPlane(vOffset1, vOffset0, v2, v3);
                            }
                        }
                        else
                        {
                            List <float> useLaterals = new List <float>();
                            List <bool>  hasPortals  = new List <bool>();
                            for (int wp = 0; wp < wallPortalCount; wp++)
                            {
                                RoomPortal portal    = wallPortals[wp];
                                bool       hasPortal = room.HasPortal(portal);
                                hasPortals.Add(hasPortal);
                                if (hasPortal)
                                {
                                    useLaterals.Add(portal.lateralPosition);
                                }
                                else
                                {
                                    useLaterals.Add(1 - portal.lateralPosition);//portal from other wall - wall orientation is flipped
                                }
                            }

                            Vector3 wallVector               = vOffset1 - vOffset0;
                            Vector3 wallDirection            = wallVector.normalized;
                            Vector3 wallStart                = vOffset0;
                            Vector4 wallTangent              = BuildRMesh.CalculateTangent(wallDirection);
                            Vector3 wallNormal               = Vector3.Cross(Vector3.up, wallDirection);
                            Vector4 wallNormalTangent        = BuildRMesh.CalculateTangent(wallNormal);
                            Vector4 wallNormalTangentReverse = BuildRMesh.CalculateTangent(-wallNormal);

                            while (wallPortalCount > 0)
                            {
                                int        portalIndex = 0;
                                RoomPortal usePortal   = wallPortals[0];
                                float      lowestLat   = useLaterals[0];
                                for (int wp = 1; wp < wallPortalCount; wp++)
                                {
                                    if (useLaterals[wp] < lowestLat)
                                    {
                                        portalIndex = wp;
                                        usePortal   = wallPortals[wp];
                                        lowestLat   = useLaterals[wp];
                                    }
                                }

                                wallPortals.RemoveAt(portalIndex);
                                useLaterals.RemoveAt(portalIndex);
                                wallPortalCount--;

                                Vector3 vl0 = v0 + (-wallNormal + wallDirection) * wallThickness;
                                Vector3 vl1 = v1 + (-wallNormal - wallDirection) * wallThickness;

                                Vector3 portalCenter     = Vector3.Lerp(vl0, vl1, lowestLat);
                                Vector3 portalHalfvector = wallDirection * (usePortal.width * 0.5f);
                                Vector3 portalBase       = Vector3.up * (volume.floorHeight - usePortal.height) * usePortal.verticalPosition;
                                Vector3 portalUp         = portalBase + Vector3.up * usePortal.height;
                                Vector3 portalStart      = portalCenter - portalHalfvector;
                                Vector3 portalEnd        = portalCenter + portalHalfvector;

                                Vector2 initalWallUVMin = new Vector2(Vector3.Dot(portalStart, wallDirection), 0);
                                Vector2 initalWallUVMax = new Vector2(Vector3.Dot(wallStart, wallDirection), wallUp);
                                mesh.AddPlane(portalStart, wallStart, portalStart + wallUpV, wallStart + wallUpV, initalWallUVMin, initalWallUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//initial wall
                                if (generateColliders)
                                {
                                    collider.AddPlane(portalStart, wallStart, portalStart + wallUpV, wallStart + wallUpV);
                                }
                                if (usePortal.verticalPosition > 0)
                                {
                                    Vector2 portalBaseUVMin = new Vector2(Vector3.Dot(portalEnd, wallDirection), 0);
                                    Vector2 portalBaseUVMax = new Vector2(Vector3.Dot(portalStart, wallDirection), portalBase.y);
                                    mesh.AddPlane(portalEnd, portalStart, portalEnd + portalBase, portalStart + portalBase, portalBaseUVMin, portalBaseUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//bottom
                                    if (generateColliders)
                                    {
                                        collider.AddPlane(portalEnd, portalStart, portalEnd + portalBase, portalStart + portalBase);
                                    }
                                }
                                if (usePortal.verticalPosition < 1)
                                {
                                    Vector2 portalBaseUVMin = new Vector2(Vector3.Dot(portalEnd, wallDirection), portalUp.y);
                                    Vector2 portalBaseUVMax = new Vector2(Vector3.Dot(portalStart, wallDirection), wallUp);
                                    mesh.AddPlane(portalEnd + portalUp, portalStart + portalUp, portalEnd + wallUpV, portalStart + wallUpV, portalBaseUVMin, portalBaseUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//top
                                    if (generateColliders)
                                    {
                                        collider.AddPlane(portalEnd + portalUp, portalStart + portalUp, portalEnd + wallUpV, portalStart + wallUpV);
                                    }
                                }

                                if (hasPortals[portalIndex])//only do this once - from the room it's attached to
                                {
                                    //portal interior frame
                                    Vector3 portalDepth = wallNormal * wallThickness * 2;

                                    //sides
                                    mesh.AddPlane(portalStart + portalDepth + portalBase, portalStart + portalBase, portalStart + portalDepth + portalUp, portalStart + portalUp, wallDirection, wallNormalTangentReverse, wallSubmesh);
                                    mesh.AddPlane(portalEnd + portalBase, portalEnd + portalDepth + portalBase, portalEnd + portalUp, portalEnd + portalDepth + portalUp, -wallDirection, wallNormalTangent, wallSubmesh);

                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalStart + portalDepth + portalBase, portalStart + portalBase, portalStart + portalDepth + portalUp, portalStart + portalUp);
                                        collider.AddPlane(portalEnd + portalBase, portalEnd + portalDepth + portalBase, portalEnd + portalUp, portalEnd + portalDepth + portalUp);
                                    }

                                    //floor
                                    Vector2 minFloorUv = new Vector2((portalEnd + portalBase).z, (portalEnd + portalBase).x);
                                    Vector2 maxFloorUv = minFloorUv + new Vector2(wallThickness, usePortal.width);
                                    mesh.AddPlane(portalStart + portalBase, portalStart + portalDepth + portalBase, portalEnd + portalBase, portalEnd + portalDepth + portalBase, minFloorUv, maxFloorUv, Vector3.up, wallTangent, floorSubmesh, floorSurface);
                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalStart + portalBase, portalStart + portalDepth + portalBase, portalEnd + portalBase, portalEnd + portalDepth + portalBase);
                                    }

                                    //ceiling
                                    mesh.AddPlane(portalEnd + portalUp, portalEnd + portalDepth + portalUp, portalStart + portalUp, portalStart + portalDepth + portalUp, Vector3.down, wallTangent, wallSubmesh);
                                    if (generateMeshColliders)
                                    {
                                        collider.AddPlane(portalEnd + portalUp, portalEnd + portalDepth + portalUp, portalStart + portalUp, portalStart + portalDepth + portalUp);
                                    }
                                }

                                wallStart = portalEnd;//move the start for the next calculation
                            }

                            Vector2 finalWallUVMin = new Vector2(Vector3.Dot(vOffset1, wallDirection), 0);
                            Vector2 finalWallUVMax = new Vector2(Vector3.Dot(wallStart, wallDirection), wallUp);
                            mesh.AddPlane(vOffset1, wallStart, vOffset1 + wallUpV, wallStart + wallUpV, finalWallUVMin, finalWallUVMax, wallNormal, wallTangent, wallSubmesh, wallSurface);//final wall section
                            if (generateColliders)
                            {
                                collider.AddPlane(vOffset1, wallStart, vOffset1 + wallUpV, wallStart + wallUpV);
                            }
                        }
                        offsetPointBase += 1;
                    }
                    else//external anchored wall
                    {
                        int    facadeIndex  = wall.facadeIndex;
                        Facade facadeDesign = volume.GetFacade(facadeIndex);
                        int    currentFacadeWallSectionLength = externalWallAnchors[facadeIndex].Count - 1;
                        int    currentWallSectionIndex        = wall.offsetPointWallSection[0];
                        int    wallOffsetPoints = wall.offsetPoints.Length;
                        for (int w = 0; w < wallOffsetPoints - 1; w++)
                        {
                            int     roomPointIndex   = offsetPointBase + w;
                            Vector2 baseA            = offsetRoomAnchorPoints[roomPointIndex];
                            int     offsetIndexB     = (roomPointIndex + 1) % offsetRoomAnchorPoints.Length;
                            Vector2 baseB            = offsetRoomAnchorPoints[offsetIndexB];
                            Vector3 v0               = new Vector3(baseA.x, 0, baseA.y) + floorBaseV;
                            Vector3 v1               = new Vector3(baseB.x, 0, baseB.y) + floorBaseV;
                            int     wallSectionIndex = wall.offsetPointWallSection[w];

                            bool canGenerateWallSection = facadeDesign != null;

                            Vector3 wallVector = v0 - v1;
                            Vector3 wallDir    = wallVector.normalized;
                            float   wallLength = wallVector.magnitude;

                            if (!canGenerateWallSection)
                            {
                                if (wallSurface != null)
                                {
                                    submeshLibrary.Add(wallSurface);
                                }

                                Vector3 v2 = v1 + wallUpV;
                                Vector3 v3 = v0 + wallUpV;

                                Vector2 minUV       = Vector2.zero;
                                Vector2 maxUV       = new Vector2(Vector2.Distance(baseA, baseB), wallUp);
                                Vector3 wallNormal  = Vector3.Cross(Vector3.up, wallDir);
                                Vector4 wallTangent = BuildRMesh.CalculateTangent(wallDir);
                                mesh.AddPlane(v1, v0, v2, v3, minUV, maxUV, wallNormal, wallTangent, wallSubmesh, wallSurface);

                                if (generateMeshColliders)
                                {
                                    collider.AddPlane(v1, v0, v2, v3);
                                }
                            }
                            else
                            {
                                WallSection section = facadeDesign.GetWallSection(wallSectionIndex, volumeFloor, currentFacadeWallSectionLength, volume.floors);
                                if (section.model != null)
                                {
                                    continue;//cannot account for custom meshes assume custom mesh does include interior mesh or if does - will be generated with the exterior
                                }
                                GenerationOutput generatedSection = GenerationOutput.CreateRawOutput();
                                Vector2          wallSectionSize  = new Vector2(wallLength, wallUp + wallThickness);
                                bool             cullOpening      = building.cullDoors && section.isDoor;
                                SubmeshLibrary   sectionLib       = new SubmeshLibrary();

                                if (wallSurface != null)
                                {
                                    sectionLib.Add(wallSurface);//add interior wall surface
                                    submeshLibrary.Add(wallSurface);
                                }

                                sectionLib.Add(section.openingSurface);//add windows - the only surface we'll use in the interior room
                                submeshLibrary.Add(section.openingSurface);

                                float offset = 0;
                                if (w == 0)
                                {
                                    offset = wallThickness;
                                }
                                if (w == wallOffsetPoints - 2)
                                {
                                    offset = -wallThickness;
                                }
                                WallSectionGenerator.Generate(section, generatedSection, wallSectionSize, true, wallThickness, cullOpening, null, sectionLib, offset);
                                int[]   mapping     = submeshLibrary.MapSubmeshes(generatedSection.raw.materials);
                                Vector3 curveNormal = Vector3.Cross(wallDir, Vector3.up);

                                Quaternion meshRot = Quaternion.LookRotation(curveNormal, Vector3.up);
                                Vector3    meshPos = new Vector3(v1.x, volume.baseHeight, v1.z) + wallDir * wallSectionSize.x + Vector3.up * wallSectionSize.y;
                                meshPos += meshRot * -new Vector3(wallSectionSize.x, wallSectionSize.y, 0) * 0.5f;
                                mesh.AddData(generatedSection.raw, mapping, meshPos, meshRot, Vector3.one);
                            }


                            currentWallSectionIndex++;
                            if (currentWallSectionIndex >= currentFacadeWallSectionLength)
                            {
                                //reached the end of the facade - move to the next one and continue
                                currentFacadeWallSectionLength = externalWallAnchors[facadeIndex].Count;
                                currentWallSectionIndex        = 0;
                            }
                        }

                        offsetPointBase += wallPointCount - 1;
                    }
                }

                //FLOOR
                Vector2[]   mainShape      = offsetRoomAnchorPoints;
                Vector2[][] floorCutPoints = floorCuts.ToArray();
                int         floorVertCount = mainShape.Length;
                for (int flc = 0; flc < floorCutPoints.Length; flc++)
                {
                    floorVertCount += floorCutPoints[flc].Length;
                }

                Vector2[] allFloorPoints  = new Vector2[floorVertCount];
                int       mainShapeLength = mainShape.Length;
                for (int ms = 0; ms < mainShapeLength; ms++)
                {
                    allFloorPoints[ms] = mainShape[ms];
                }
                int cutPointIterator = mainShapeLength;
                for (int flc = 0; flc < floorCutPoints.Length; flc++)
                {
                    for (int flcp = 0; flcp < floorCutPoints[flc].Length; flcp++)
                    {
                        allFloorPoints[cutPointIterator] = floorCutPoints[flc][flcp];
                        cutPointIterator++;
                    }
                }

                Vector3[] floorPoints   = new Vector3[floorVertCount];
                Vector2[] floorUvs      = new Vector2[floorVertCount];
                Vector3[] floorNorms    = new Vector3[floorVertCount];
                Vector4[] floorTangents = new Vector4[floorVertCount];
                for (int rp = 0; rp < floorVertCount; rp++)
                {
                    floorPoints[rp] = new Vector3(allFloorPoints[rp].x, 0, allFloorPoints[rp].y) + floorBaseV;
                    Vector2 uv = allFloorPoints[rp];
                    if (floorSurface != null)
                    {
                        uv = floorSurface.CalculateUV(uv);
                    }
                    floorUvs[rp]      = uv;
                    floorNorms[rp]    = Vector3.up;
                    floorTangents[rp] = tangent;
                }

                int[] tris = Poly2TriWrapper.Triangulate(mainShape, true, floorCutPoints);

                mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, floorSubmesh);
                if (generateColliders)
                {
                    collider.mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, 0);
                }

                //CEILING!
                Vector2[][] ceilingCutPoints = ceilingCuts.ToArray();
                int         ceilingVertCount = mainShape.Length;
                for (int flc = 0; flc < ceilingCutPoints.Length; flc++)
                {
                    ceilingVertCount += ceilingCutPoints[flc].Length;
                }

                Vector2[] allCeilingPoints = new Vector2[ceilingVertCount];
                for (int ms = 0; ms < mainShapeLength; ms++)
                {
                    allCeilingPoints[ms] = mainShape[ms];
                }
                cutPointIterator = mainShapeLength;
                for (int flc = 0; flc < ceilingCutPoints.Length; flc++)
                {
                    for (int flcp = 0; flcp < ceilingCutPoints[flc].Length; flcp++)
                    {
                        allCeilingPoints[cutPointIterator] = ceilingCutPoints[flc][flcp];
                        cutPointIterator++;
                    }
                }

                Vector3[] ceilingPoints   = new Vector3[ceilingVertCount];
                Vector2[] ceilingUvs      = new Vector2[ceilingVertCount];
                Vector3[] ceilingNorms    = new Vector3[ceilingVertCount];
                Vector4[] ceilingTangents = new Vector4[ceilingVertCount];
                for (int rp = 0; rp < ceilingVertCount; rp++)
                {
                    ceilingPoints[rp] = new Vector3(allCeilingPoints[rp].x, wallUp, allCeilingPoints[rp].y) + floorBaseV;
                    Vector2 uv = allCeilingPoints[rp];
                    if (floorSurface != null)
                    {
                        uv = ceilingSurface.CalculateUV(uv);
                    }
                    ceilingUvs[rp]      = uv;
                    ceilingNorms[rp]    = Vector3.down;
                    ceilingTangents[rp] = tangent;
                }

                tris = Poly2TriWrapper.Triangulate(mainShape, false, ceilingCutPoints);
                mesh.AddData(ceilingPoints, ceilingUvs, tris, ceilingNorms, ceilingTangents, ceilingSubmesh);
                if (generateColliders)
                {
                    collider.mesh.AddData(ceilingPoints, ceilingUvs, tris, ceilingNorms, ceilingTangents, 0);
                }

                for (int ob = 0; ob < openingCount; ob++)
                {
                    VerticalOpening opening      = openings[ob];
                    int             openingIndex = Array.IndexOf(openings, opening);
                    Vector3         basePosition = openingBounds[openingIndex].center;
                    basePosition.z = basePosition.y;
                    basePosition.y = volume.baseHeight;

                    if (roomOpenings.Contains(opening))//opening used in this floorplan
                    {
                        int externalWallSubmesh = wallSubmesh != -1 ? wallSubmesh : -1;
                        switch (opening.usage)
                        {
                        case VerticalOpening.Usages.Space:
                            if (ceilingCutPoints.Length <= ob)
                            {
                                continue;
                            }
                            Vector3   ceilingCutUpV = Vector3.up * wallThickness;
                            Vector2[] ceilingCut    = ceilingCutPoints[ob];
                            int       custSize      = ceilingCut.Length;
                            for (int cp = 0; cp < custSize; cp++)
                            {
                                int     indexA = (cp + 1) % custSize;
                                int     indexB = cp;
                                Vector3 cp0    = new Vector3(ceilingCut[indexA].x, wallUp, ceilingCut[indexA].y) + floorBaseV;
                                Vector3 cp1    = new Vector3(ceilingCut[indexB].x, wallUp, ceilingCut[indexB].y) + floorBaseV;
                                Vector3 cp2    = cp0 + ceilingCutUpV;
                                Vector3 cp3    = cp1 + ceilingCutUpV;
                                mesh.AddPlane(cp0, cp1, cp2, cp3, ceilingSubmesh);
                                if (generateColliders)
                                {
                                    collider.AddPlane(cp0, cp1, cp2, cp3);
                                }
                            }
                            break;

                        case VerticalOpening.Usages.Stairwell:
                            StaircaseGenerator.Generate(mesh, opening, basePosition, volume.floorHeight, actualFloor, externalWallSubmesh, sendCollider);
                            if (volumeFloor == volume.floors - 1 && opening.baseFloor + opening.floors > building.VolumeBaseFloor(volume) + volume.floors - 1 && volume.abovePlanCount == 0)
                            {
                                StaircaseGenerator.GenerateRoofAccess(mesh, opening, basePosition, volume.floorHeight, actualFloor, externalWallSubmesh, sendCollider);
                            }
                            break;

                        case VerticalOpening.Usages.Elevator:
                            ElevatorShaftGenerator.Generate(ref mesh, opening, actualFloor, basePosition, volume.floorHeight, externalWallSubmesh, sendCollider);
                            break;
                        }
                    }
                }
            }

            for (int ob = 0; ob < openingCount; ob++)
            {
                Vector2[] openingShape = openingShapes[ob];
                if (openingShape == null)
                {
                    continue;                      //opening not used by this floorplan
                }
                if (openingUsedInThisFloor[ob])
                {
                    continue;                            //opening already generated
                }
                //seal this opening from the void
                VerticalOpening opening      = openings[ob];
                int             openingIndex = Array.IndexOf(openings, opening);
                Vector3         basePosition = openingBounds[openingIndex].center;
                basePosition.z = basePosition.y;
                basePosition.y = 0;

                int       cutSize            = openingShape.Length;
                Vector3   sealingWallUpV     = Vector3.up * volume.floorHeight;
                int       sealWallSubmesh    = submeshLibrary.SubmeshAdd(opening.surfaceB);
                Vector2[] offsetOpeningShape = QuickPolyOffset.Execute(openingShape, wallThickness);
                for (int cp = 0; cp < cutSize; cp++)
                {
                    int     indexA = (cp + 1) % cutSize;
                    int     indexB = cp;
                    Vector2 p0     = opening.usage == VerticalOpening.Usages.Space ? openingShape[indexA] : offsetOpeningShape[indexA];
                    Vector2 p1     = opening.usage == VerticalOpening.Usages.Space ? openingShape[indexB] : offsetOpeningShape[indexB];
                    Vector3 cp0    = new Vector3(p0.x, 0, p0.y) + floorBaseV;
                    Vector3 cp1    = new Vector3(p1.x, 0, p1.y) + floorBaseV;
                    Vector3 cp2    = cp0 + sealingWallUpV;
                    Vector3 cp3    = cp1 + sealingWallUpV;
                    mesh.AddPlane(cp0, cp1, cp2, cp3, sealWallSubmesh);
                    if (generateColliders)
                    {
                        collider.AddPlane(cp0, cp1, cp2, cp3);
                    }
                }

                switch (opening.usage)
                {
                case VerticalOpening.Usages.Space:
                    //nothing to implement
                    break;

                case VerticalOpening.Usages.Stairwell:
                    //need stairs to connect used floors
                    StaircaseGenerator.GenerateStairs(mesh, opening, basePosition, volume.floorHeight, actualFloor, -1, sendCollider);
                    if (volumeFloor == volume.floors - 1)
                    {
                        StaircaseGenerator.GenerateRoofAccess(mesh, opening, basePosition, volume.floorHeight, actualFloor, -1, sendCollider);
                    }
                    break;

                case VerticalOpening.Usages.Elevator:
                    //nothing to implement
                    break;
                }
            }
        }
Example #8
0
        public static void BMesh(BuildRMesh mesh, float height, Surface surface, int submesh, Vector2[] shape, Rect clampUV, bool flipTri = false, Vector2[][] holes = null, BuildRCollider collider = null)
        {
            int shapeSize = shape.Length;

            bool[] useHole = new bool[0];
            if (holes != null)
            {
                int holeCount = holes.Length;
//                Debug.Log("BMesh "+holeCount);
                useHole = new bool[holeCount];
                for (int flc = 0; flc < holeCount; flc++)
                {
                    useHole[flc] = true;
                    int holeSize = holes[flc].Length;

//                    for(int h = 0; h < holeSize; h++)
//                    {
//                        Vector2 holePoint = holes[flc][h];
//                        holeIntersections[h] = PointInShape(holePoint, shape);
////                        Debug.Log("intersection length " + intersections.Length);
//                        useHole[flc] = holeIntersections[h].Length == 0;
//                    }

                    //                    for(int flcp = 0; flcp < holeSize; flcp++)
                    //                    {
//                                            if(!PointInPolygon(holes[flc][flcp], shape))
                    //                        {
                    //                            useHole[flc] = false;
                    //                            break;
                    //                        }
                    //                    }
                    if (useHole[flc])
                    {
                        shapeSize += holeSize;
                    }
                }
            }

            Vector2[] allFloorPoints  = new Vector2[shapeSize];
            int       mainShapeLength = shape.Length;

            for (int ms = 0; ms < mainShapeLength; ms++)
            {
                allFloorPoints[ms] = shape[ms];
            }
            int cutPointIterator = mainShapeLength;

            if (holes != null)
            {
                for (int flc = 0; flc < holes.Length; flc++)
                {
                    if (!useHole[flc])
                    {
                        continue;
                    }
                    for (int flcp = 0; flcp < holes[flc].Length; flcp++)
                    {
                        allFloorPoints[cutPointIterator] = holes[flc][flcp];
                        cutPointIterator++;
                    }
                }
            }

            FlatBounds bounds = new FlatBounds();

            if (clampUV.width > 0)
            {
                for (int fvc = 0; fvc < mainShapeLength; fvc++)
                {
                    bounds.Encapsulate(shape[fvc]);
                }
            }

            Vector3[] floorPoints   = new Vector3[shapeSize];
            Vector2[] floorUvs      = new Vector2[shapeSize];
            Vector3[] floorNorms    = new Vector3[shapeSize];
            Vector4[] floorTangents = new Vector4[shapeSize];
            Vector3   normal        = flipTri ? Vector3.up : Vector3.down;
            Vector4   tangent       = BuildRMesh.CalculateTangent(Vector3.right);

            for (int rp = 0; rp < shapeSize; rp++)
            {
                floorPoints[rp] = new Vector3(allFloorPoints[rp].x, height, allFloorPoints[rp].y);
                if (clampUV.width > 0)
                {
                    Vector2 clampedUV = new Vector2();
                    clampedUV.x  = ((floorPoints[rp].x - bounds.xMin) / bounds.width) * clampUV.width + clampUV.x;
                    clampedUV.y  = ((floorPoints[rp].z - bounds.yMin) / bounds.height) * clampUV.height + clampUV.y;
                    floorUvs[rp] = clampedUV;
                }
                else
                {
                    if (surface != null)
                    {
                        floorUvs[rp] = surface.CalculateUV(allFloorPoints[rp]);
                    }
                    else
                    {
                        floorUvs[rp] = allFloorPoints[rp];
                    }
                }
                floorNorms[rp]    = normal;
                floorTangents[rp] = tangent;
            }

            int[] tris = Triangulate(shape, flipTri, holes);

            //                Debug.Log(volumeFloor + " " + actualFloor + " " + floorPoints.Length + " " + tris.Length+" "+r);
            int useFloorSubmesh = submesh != -1 ? submesh : 0;

            mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, useFloorSubmesh);
            if (collider != null)
            {
                collider.mesh.AddData(floorPoints, floorUvs, tris, floorNorms, floorTangents, 0);
            }
        }
Example #9
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);
            }
        }