Esempio n. 1
0
    public static RawMeshData CopyBuildRMesh(BuildRMesh data)
    {
        RawMeshData output = new RawMeshData(data.vertices.Count, data.triangles.Count);

        output.Copy(data);
        return(output);
    }
    /// <summary>
    /// Instantiates a new cut slice
    /// </summary>
    /// <param name="data"></param>
    private void InstantiateSlice(RawMeshData data)
    {
        SlicedObject slice = Instantiate(_slicePrefab, transform).GetComponent <SlicedObject>();

        slice.Init(data.MeshTransform, data.ToMesh());
        _objectsOnScene.Add(slice);
    }
Esempio n. 3
0
        public void UpdateDirty()
        {
            if (!dirty)
            {
                return;
            }
            dirty = false;

            ((HermiteDataGrid)grid).Save(TWDir.Test.CreateSubdirectory("DualContouring").CreateFile("InteractiveGrid.txt"));


            lastSurfaceExtractionTime = PerformanceHelper.Measure(() =>
            {
                surfaceMesh = dcMeshBuilder.buildRawMesh(grid);
            });

            if (meshElement != null)
            {
                meshElement.Delete();
            }
            meshElement             = surfaceRenderer.CreateSurface(grid, Matrix.Identity);
            meshElement.WorldMatrix = Matrix.Scaling(new Vector3(CellSize));

            this.lines.ClearAllLines();
            addHermiteVertices(grid, CellSize, this.lines);
            addQEFPoints(surfaceMesh, CellSize, this.lines);
            addHermiteNormals(grid, CellSize, this.lines);

            lines.AddBox(new BoundingBox(new Vector3(), grid.Dimensions.ToVector3() * cellSize), Color.Black);
        }
Esempio n. 4
0
    public static RawMeshData CopMesh(Mesh data)
    {
        RawMeshData output = new RawMeshData(data.vertices.Length, data.triangles.Length);

        output.Copy(data);
        return(output);
    }
Esempio n. 5
0
    /// <summary>
    /// Computes intersection point vor 2 verts and a plane in mesh local space
    /// </summary>
    /// <param name="plane"></param>
    /// <param name="p1"></param>
    /// <param name="p2"></param>
    /// <param name="mesh"></param>
    /// <returns></returns>
    private Vector3 GetLocalIntersectionPoint(Plane plane, Vector3 p1, Vector3 p2, RawMeshData mesh)
    {
        //computing verts world position;
        Vector3 p0World = mesh.MeshTransform.TransformPoint(p1);
        Vector3 p1World = mesh.MeshTransform.TransformPoint(p2);

        return(mesh.MeshTransform.InverseTransformPoint(PlaneLineIntersection(_cutterPlane, p0World, p1World)));
    }
Esempio n. 6
0
    /// <summary>
    /// Triangle Cut logic for triangle (0,1)|(2)
    /// </summary>
    /// <param name="triangle"></param>
    /// <param name="originSide"></param>
    /// <param name="alienSide"></param>
    /// <returns></returns>
    private List <Vector3> CreateP01Cut(Triangle triangle, RawMeshData originSide, RawMeshData alienSide)
    {
        List <Vector3> cutEdge = new List <Vector3>();

        //getting verts values by triangle
        Vector3 p0Val = _originalMesh.vertices[triangle.P0];
        Vector3 p1Val = _originalMesh.vertices[triangle.P1];
        Vector3 p2Val = _originalMesh.vertices[triangle.P2];

        //computing plane/tri intersection points
        Vector3 intersection1 = GetLocalIntersectionPoint(_cutterPlane, p0Val, p2Val, originSide);
        Vector3 intersection2 = GetLocalIntersectionPoint(_cutterPlane, p1Val, p2Val, originSide);

        //adding new vertices on one side of the plane
        originSide.Verts.AddLast(p0Val);
        originSide.Verts.AddLast(p1Val);
        originSide.Verts.AddLast(intersection2);
        originSide.Verts.AddLast(intersection1);

        //generating triangles on these vertices
        originSide.Tris.AddLast(new Triangle(
                                    originSide.Verts.Count - 3,
                                    originSide.Verts.Count - 2,
                                    originSide.Verts.Count - 4)
                                );
        originSide.Tris.AddLast(new Triangle(
                                    originSide.Verts.Count - 4,
                                    originSide.Verts.Count - 2,
                                    originSide.Verts.Count - 1)
                                );

        //adding new vertices on other side of the plane
        alienSide.Verts.AddLast(intersection1);
        alienSide.Verts.AddLast(intersection2);
        alienSide.Verts.AddLast(p2Val);

        //generating triangles on these vertices
        alienSide.Tris.AddLast(new Triangle(
                                   alienSide.Verts.Count - 3,
                                   alienSide.Verts.Count - 2,
                                   alienSide.Verts.Count - 1)
                               );

        //adding intersections as edge points order dependent on origin side relatively to a plane

        if (originSide.Equals(_posSubMesh))
        {
            cutEdge.Add(intersection2);
            cutEdge.Add(intersection1);
        }
        else
        {
            cutEdge.Add(intersection1);
            cutEdge.Add(intersection2);
        }
        return(cutEdge);
    }
Esempio n. 7
0
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="originalMesh"></param>
    /// <param name="posSubMesh"></param>
    /// <param name="negSubMesh"></param>
    /// <param name="cutterPlane"></param>
    public Cut(Mesh originalMesh, RawMeshData posSubMesh, RawMeshData negSubMesh, Plane cutterPlane)
    {
        _originalMesh = originalMesh;
        _posSubMesh   = posSubMesh;
        _negSubMesh   = negSubMesh;
        _cutterPlane  = cutterPlane;

        Meshes = new List <RawMeshData>();
        CutMesh();
    }
Esempio n. 8
0
 public static void addQEFPoints(RawMeshData mesh, float scale, LineManager3DLines lineManager3DLines)
 {
     if (mesh.Positions.Length == 0)
     {
         return;
     }
     foreach (var p in mesh.Positions)
     {
         lineManager3DLines.AddCenteredBox(p * scale, 0.05f, Color.Orange);
     }
 }
Esempio n. 9
0
        public VoxelSurface CreateSurface(AbstractHermiteGrid grid, Matrix world)
        {
            var vertices  = new List <Vector3>();
            var indices   = new List <int>();
            var materials = new List <DCVoxelMaterial>();

            var algo = new DualContouringAlgorithm();

            algo.GenerateSurface(vertices, indices, materials, grid);


            var triangleNormals = dcMeshBuilder.generateTriangleNormals(indices, vertices);

            var uniqueMaterials = materials.Distinct().ToArray();

            if (!uniqueMaterials.Any())
            {
                return new VoxelSurface(this)
                       {
                           WorldMatrix = world
                       }
            }
            ;


            var ret = new VoxelSurface(this);

            ret.WorldMatrix = world;
            surfaces.Add(ret);


            foreach (var imat in uniqueMaterials)
            {
                var mat = imat;


                var mesh = new RawMeshData(
                    indices.Where((i, index) => materials[index / 3] == mat).Select(i => vertices[i].dx()).ToArray(),
                    indices.Select((i, index) => triangleNormals[index / 3].dx()).Where((i, index) => materials[index / 3] == mat).ToArray(),
                    indices.Where((i, index) => materials[index / 3] == mat).Select(i => new Vector2().dx()).ToArray(),
                    indices.Where((i, index) => materials[index / 3] == mat).Select(i => new Vector3().dx()).ToArray()
                    );

                var actualMat = mat;
                if (actualMat == null)
                {
                    actualMat = defaultMaterial;
                }
                ret.MeshesWithMaterial.Add(new MeshWithMaterial(mesh, actualMat, renderDataFactory.CreateMeshPartData(mesh)));
            }

            return(ret);
        }
Esempio n. 10
0
 public void DetectTriangleOriginSide(RawMeshData posVerts, RawMeshData negVerts, out RawMeshData origin, out RawMeshData alien)
 {
     if (posVerts.VertsIndexes.Contains(P0))
     {
         origin = posVerts;
         alien  = negVerts;
     }
     else
     {
         origin = negVerts;
         alien  = posVerts;
     }
 }
Esempio n. 11
0
 public TriangleCutTypeOrigin DetectTriangleCutType(RawMeshData origin)
 {
     if (origin.VertsIndexes.Contains(P1))
     {
         return(TriangleCutTypeOrigin.P01);
     }
     else if (origin.VertsIndexes.Contains(P2))
     {
         return(TriangleCutTypeOrigin.P20);
     }
     else
     {
         return(TriangleCutTypeOrigin.P0);
     }
 }
Esempio n. 12
0
    /// <summary>
    /// Divides vertices into two parts
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="cutterPlane"></param>
    /// <param name="meshTransform"></param>
    /// <param name="verts"></param>
    /// <param name="pos"></param>
    /// <param name="neg"></param>
    private static void DivideVerticesToPosAndNegSubmeshes(Mesh mesh, Plane cutterPlane, Transform meshTransform, Vector3[] verts, out RawMeshData pos, out RawMeshData neg)
    {
        pos = new RawMeshData(mesh, meshTransform);
        neg = new RawMeshData(mesh, meshTransform);

        for (int i = 0; i < verts.Length; i++)
        {
            if (cutterPlane.GetSide(meshTransform.TransformPoint(verts[i])))
            {
                pos.VertsIndexes.AddLast(i);
            }
            else
            {
                neg.VertsIndexes.AddLast(i);
            }
        }
    }
        public RawMeshData buildRawMesh(AbstractHermiteGrid grid)
        {
            var vertices = new List <Vector3>();
            var indices  = new List <int>();
            var algo     = new DualContouringAlgorithm();

            algo.GenerateSurface(vertices, indices, grid);


            var triangleNormals = generateTriangleNormals(indices, vertices);

            var ret = new RawMeshData(indices.Select(i => vertices[i].dx()).ToArray(),
                                      indices.Select((index, numIndex) => triangleNormals[numIndex / 3].dx()).ToArray(),
                                      indices.Select(i => new Vector2().dx()).ToArray(),
                                      indices.Select(i => new Vector3().dx()).ToArray());

            return(ret);
        }
        public MeshPartRenderData CreateMeshPartData(RawMeshData rawMeshData)
        {
            var data = new MeshPartRenderData();

            int vertCount = rawMeshData.Positions.Length;

            if (vertCount == 0)
            {
                throw new InvalidOperationException();
            }

            data.IndexBuffer  = CreateMeshPartIndexBuffer(rawMeshData.Positions);
            data.VertexBuffer = CreateMeshPartVertexBuffer(rawMeshData.Positions, rawMeshData.Normals, rawMeshData.Texcoords, rawMeshData.Tangents);

            //data.VertexCount = vertCount;
            data.PrimitiveCount = vertCount / 3;

            return(data);
        }
Esempio n. 15
0
        public static RawMeshData GeneratePlot(IPlot plot)
        {
            int pointSize = plot.numberOfEdges;

            int[]     sortedIndexes = BuildrUtils.SortPointByAngle(plot.pointsV2, plot.center);
            Vector2[] sortedPoints  = new Vector2[pointSize];
            for (int i = 0; i < pointSize; i++)
            {
                sortedPoints[i] = plot.pointsV2[sortedIndexes[i]];
            }
            bool clockwise = Clockwise(sortedPoints);

            int vertCount = pointSize + 1;
            int triCount  = pointSize * 3;

            RawMeshData output = new RawMeshData(vertCount, triCount);

            for (int v = 0; v < vertCount - 1; v++)
            {
                output.vertices[v] = new Vector3(sortedPoints[v].x, 0, sortedPoints[v].y);
            }
            output.vertices[vertCount - 1] = new Vector3(plot.center.x, 0, plot.center.y);

            int vertIndex = 0;

            for (int t = 0; t < triCount; t += 3)
            {
                output.triangles[t + 0] = vertCount - 1;
                if (clockwise)
                {
                    output.triangles[t + 1] = vertIndex;
                    output.triangles[t + 2] = (vertIndex < vertCount - 2) ? vertIndex + 1 : 0;
                }
                else
                {
                    output.triangles[t + 1] = (vertIndex < vertCount - 2) ? vertIndex + 1 : 0;
                    output.triangles[t + 2] = vertIndex;
                }
                vertIndex++;
            }

            return(output);
        }
Esempio n. 16
0
    /// <summary>
    /// Tels wheather a mesh is intersected by a plane
    /// </summary>
    /// <param name="cutterPlane"></param>
    /// <param name="mesh"></param>
    /// <param name="transform"></param>
    /// <param name="pos"></param>
    /// <param name="neg"></param>
    /// <returns>true if does</returns>
    private static bool IsMeshIntersectedByPlane(Plane cutterPlane, Mesh mesh, Transform transform, out RawMeshData pos, out RawMeshData neg)
    {
        pos = new RawMeshData(mesh, transform);
        neg = new RawMeshData(mesh, transform);

        if (!mesh.bounds.IsIntersectedByPlane(cutterPlane, transform))
        {
            return(false);
        }

        else
        {
            DivideVerticesToPosAndNegSubmeshes(mesh, cutterPlane, transform, mesh.vertices, out pos, out neg);

            if (pos.VertsIndexes.Count == 0 || neg.VertsIndexes.Count == 0)
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
    }
Esempio n. 17
0
/// <summary>
/// Ads a cap for the hull data
/// </summary>
/// <param name="data"></param>
/// <param name="edge"></param>
/// <param name="inverted"></param>
    private void AddCap(RawMeshData data, List <Vector3> edge, bool inverted)
    {
        Vector3 capCenter = Utils.ComputeCenter(edge);

        edge.Add(capCenter);
        int VertsCount = data.Verts.Count;

        data.Verts.AddRange(edge);

        if (inverted)
        {
            for (int i = VertsCount; i < data.Verts.Count - 2; i += 2)
            {
                data.Tris.AddLast(new Triangle(i, i + 1, data.Verts.Count - 1));
            }
        }
        else
        {
            for (int i = VertsCount; i < data.Verts.Count - 2; i += 2)
            {
                data.Tris.AddLast(new Triangle(i + 1, i, data.Verts.Count - 1));
            }
        }
    }
Esempio n. 18
0
        public static void GenerateFacade(FacadeData data, BuildRMesh dmesh, BuildRCollider collider = null)
        {
//		    Debug.Log("******************* "+data.facadeDesign.ToString());
            Vector3 facadeVector = data.baseB - data.baseA;

            if (facadeVector.magnitude < Mathf.Epsilon)
            {
                return;
            }
            Vector3   facadeDirection = facadeVector.normalized;
            Vector3   facadeNormal    = Vector3.Cross(facadeDirection, Vector3.up);
            Vector4   facadeTangent   = BuildRMesh.CalculateTangent(facadeDirection);
            RandomGen rGen            = new RandomGen();

            rGen.GenerateNewSeed();
            float                 wallThickness = data.wallThickness;
            float                 foundation    = data.foundationDepth;
            BuildingMeshTypes     meshType      = data.meshType;
            BuildingColliderTypes colliderType  = data.colliderType;
            int     wallSections = 0;
            Vector2 wallSectionSize;
            float   facadeLength = 0;

            if (data.isStraight)
            {
                facadeLength = facadeVector.magnitude;
                wallSections = Mathf.FloorToInt(facadeLength / data.minimumWallUnitLength);
                if (wallSections < 1)
                {
                    wallSections = 1;
                }
                wallSectionSize = new Vector2(facadeLength / wallSections, data.floorHeight);
            }
            else
            {
                wallSections = data.anchors.Count - 1;
                if (wallSections < 1)
                {
                    wallSections = 1;
                }
                float sectionWidth = Vector2.Distance(data.anchors[0].vector2, data.anchors[1].vector2);
                wallSectionSize = new Vector2(sectionWidth, data.floorHeight);
            }

            Dictionary <WallSection, RawMeshData>           generatedSections                  = new Dictionary <WallSection, RawMeshData>();
            Dictionary <WallSection, RawMeshData>           generatedSectionMeshColliders      = new Dictionary <WallSection, RawMeshData>();
            Dictionary <WallSection, BuildRCollider.BBox[]> generatedSectionPrimitiveColliders = new Dictionary <WallSection, BuildRCollider.BBox[]>();

            int startFloor = data.startFloor;

//		    Debug.Log("st fl "+startFloor);
//		    Debug.Log("fl ct "+ data.floorCount);
            for (int fl = startFloor; fl < data.floorCount; fl++)
            {
//			    Debug.Log(fl);
                if (data.facadeDesign.randomisationMode == Facade.RandomisationModes.RandomRows)
                {
                    generatedSections.Clear();                                                                             //recalculate each row
                }
//			    Debug.Log(wallSections);
                for (int s = 0; s < wallSections; s++)
                {
//				    Debug.Log(s);
                    WallSection section = data.facadeDesign.GetWallSection(s, fl + data.actualStartFloor, wallSections, data.floorCount);
//				    Debug.Log(section);
                    dmesh.submeshLibrary.Add(section);                    //add the wallsection to the main submesh library
                    RawMeshData generatedSection         = null;
                    RawMeshData generatedSectionCollider = null;

                    BuildRCollider.BBox[] bboxes = new BuildRCollider.BBox[0];

                    if (section == null)
                    {
                        GenerationOutput output         = GenerationOutput.CreateRawOutput();
                        GenerationOutput outputCollider = null;
                        if (colliderType == BuildingColliderTypes.Complex)
                        {
                            outputCollider = GenerationOutput.CreateRawOutput();
                        }
                        if (colliderType == BuildingColliderTypes.Primitive)
                        {
                            BuildRCollider.BBox[] bbox = WallSectionGenerator.Generate(section, wallSectionSize, wallThickness);
                            generatedSectionPrimitiveColliders.Add(section, bbox);
                        }
                        WallSectionGenerator.Generate(section, output, wallSectionSize, false, wallThickness, true, outputCollider, dmesh.submeshLibrary);

                        generatedSection = output.raw;
                        if (outputCollider != null)
                        {
                            generatedSectionCollider = outputCollider.raw;
                        }
                    }
                    else
                    {
                        if (generatedSections.ContainsKey(section))
                        {
                            generatedSection = generatedSections[section];
                            if (generatedSectionMeshColliders.ContainsKey(section))
                            {
                                generatedSectionCollider = generatedSectionMeshColliders[section];
                            }
                        }
                        else
                        {
                            GenerationOutput output         = GenerationOutput.CreateRawOutput();
                            GenerationOutput outputCollider = null;
                            bool             cullOpening    = data.cullDoors && section.isDoor;
                            if (colliderType == BuildingColliderTypes.Complex)
                            {
                                outputCollider = GenerationOutput.CreateRawOutput();
                            }
                            if (colliderType == BuildingColliderTypes.Primitive)
                            {
                                BuildRCollider.BBox[] bbox = WallSectionGenerator.Generate(section, wallSectionSize, wallThickness, cullOpening);
                                generatedSectionPrimitiveColliders.Add(section, bbox);
                            }
                            WallSectionGenerator.Generate(section, output, wallSectionSize, false, wallThickness, cullOpening, outputCollider, dmesh.submeshLibrary);

                            generatedSections.Add(section, output.raw);
                            if (generatedSectionCollider != null)
                            {
                                generatedSectionMeshColliders.Add(section, outputCollider.raw);
                            }

                            generatedSection = output.raw;
                            if (generatedSectionCollider != null)
                            {
                                generatedSectionCollider = outputCollider.raw;
                            }
                        }

                        if (generatedSectionPrimitiveColliders.ContainsKey(section))
                        {
                            bboxes = generatedSectionPrimitiveColliders[section];
                        }
                    }

//				    Debug.Log("data strt" + data.isStraight);
                    if (data.isStraight)
                    {
                        Quaternion meshRot           = Quaternion.LookRotation(facadeNormal, Vector3.up);
                        Vector3    baseMeshPos       = data.baseA + facadeDirection * wallSectionSize.x + Vector3.up * wallSectionSize.y;
                        Vector3    wallSectionVector = new Vector3(wallSectionSize.x * s, wallSectionSize.y * fl, 0);
                        baseMeshPos += meshRot * wallSectionVector;
                        Vector3 meshPos = baseMeshPos + meshRot * -wallSectionSize * 0.5f;

                        Vector2 uvOffset       = new Vector2(wallSectionSize.x * s, wallSectionSize.y * fl);
                        Vector2 uvOffsetScaled = uvOffset;
                        if (section != null && section.wallSurface != null)
                        {
                            uvOffsetScaled = CalculateUv(uvOffsetScaled, section.wallSurface);
                        }

                        //TODO account for the mesh mode of the wall section - custom meshes
                        if (meshType == BuildingMeshTypes.Full)
                        {
                            dmesh.AddData(generatedSection, meshPos, meshRot, Vector3.one, uvOffsetScaled);
                        }
                        if (collider != null && generatedSectionCollider != null)
                        {
                            collider.mesh.AddData(generatedSectionCollider, meshPos, meshRot, Vector3.one);
                        }
                        if (collider != null && bboxes.Length > 0)
                        {
                            collider.AddBBox(bboxes, meshPos, meshRot);
                        }

//					    Debug.Log("foundation");
                        if (fl == 0 && foundation > Mathf.Epsilon)
                        {
                            Vector3 fp3 = baseMeshPos + Vector3.down * wallSectionSize.y;
                            Vector3 fp2 = fp3 - facadeDirection * wallSectionSize.x;
                            Vector3 fp0 = fp2 + Vector3.down * foundation;
                            Vector3 fp1 = fp3 + Vector3.down * foundation;

                            if (meshType == BuildingMeshTypes.Full)
                            {
                                Surface foundationSurface = data.foundationSurface != null ? data.foundationSurface : section.wallSurface;
                                int     foundationSubmesh = dmesh.submeshLibrary.SubmeshAdd(foundationSurface);                            //facadeSurfaces.IndexOf(section.wallSurface));
                                dmesh.AddPlane(fp0, fp1, fp2, fp3, new Vector2(uvOffset.x, -foundation), new Vector2(uvOffset.x + wallSectionSize.x, 0), -facadeNormal, facadeTangent, foundationSubmesh, foundationSurface);
                            }
                            if (collider != null && generatedSectionCollider != null)
                            {
                                collider.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                            }
                        }
                    }
                    else
                    {
                        //todo switch - support wall section based curves for now

                        Vector3 cp0 = data.anchors[s].vector3XZ;
                        cp0.y = data.baseA.y;
                        Vector3 cp1 = data.anchors[s + 1].vector3XZ;
                        cp1.y = data.baseA.y;
                        Vector3 curveVector    = cp1 - cp0;
                        Vector3 curveDirection = curveVector.normalized;
                        Vector3 curveNormal    = Vector3.Cross(curveDirection, Vector3.up);
                        float   actualWidth    = curveVector.magnitude;

                        Quaternion meshRot           = Quaternion.LookRotation(curveNormal, Vector3.up);
                        Vector3    meshPos           = cp1 + Vector3.up * wallSectionSize.y;
                        Vector3    wallSectionVector = new Vector3(0, wallSectionSize.y * fl, 0);
                        meshPos += meshRot * wallSectionVector;
                        meshPos += meshRot * -new Vector3(actualWidth, wallSectionSize.y, 0) * 0.5f;
                        Vector3 meshScale = new Vector3(actualWidth / wallSectionSize.x, 1, 1);

                        //Thanks Anthony Cuellar - issue #12
                        Vector2 uvOffset       = new Vector2(wallSectionVector.x, wallSectionVector.y + (section.hasOpening ? 0 : wallSectionSize.y / 2f));
                        Vector2 uvOffsetScaled = CalculateUv(uvOffset, section.wallSurface);
                        //TODO account for the mesh mode of the wall section - custom meshes
                        if (meshType == BuildingMeshTypes.Full)
                        {
                            dmesh.AddData(generatedSection, meshPos, meshRot, meshScale, uvOffsetScaled);
                        }
                        if (collider != null && generatedSectionCollider != null)
                        {
                            collider.mesh.AddData(generatedSectionCollider, meshPos, meshRot, meshScale);
                        }
                        if (collider != null && bboxes.Length > 0)
                        {
                            collider.AddBBox(bboxes, meshPos, meshRot);
                        }

//					    Debug.Log("foundation");
                        if (fl == 0 && foundation > Mathf.Epsilon)
                        {
                            Vector3 fp3 = cp1;
                            Vector3 fp2 = fp3 - curveDirection * actualWidth;
                            Vector3 fp0 = fp2 + Vector3.down * foundation;
                            Vector3 fp1 = fp3 + Vector3.down * foundation;

                            if (meshType == BuildingMeshTypes.Full)
                            {
                                Surface foundationSurface = data.foundationSurface != null ? data.foundationSurface : section.wallSurface;
                                int     foundationSubmesh = dmesh.submeshLibrary.SubmeshAdd(foundationSurface);                            //facadeSurfaces.IndexOf(section.wallSurface);
                                dmesh.AddPlane(fp0, fp1, fp2, fp3, new Vector2(uvOffset.x, -foundation), new Vector2(uvOffset.x + actualWidth, 0), -curveNormal, facadeTangent, foundationSubmesh, foundationSurface);
                            }
                            if (collider != null && generatedSectionCollider != null)
                            {
                                collider.mesh.AddPlane(fp0, fp1, fp2, fp3, 0);
                            }
                        }
                    }
                }

                //string course is completely ignored for a collision
//			    Debug.Log("string");
                if (fl > 0 && data.facadeDesign.stringCourse && meshType == BuildingMeshTypes.Full)                //no string course on ground floor
                {
                    float   baseStringCoursePosition = wallSectionSize.y * fl + wallSectionSize.y * data.facadeDesign.stringCoursePosition;
                    Vector3 scBaseUp = baseStringCoursePosition * Vector3.up;
                    Vector3 scTopUp  = (data.facadeDesign.stringCourseHeight + baseStringCoursePosition) * Vector3.up;
                    if (data.isStraight)
                    {
                        Vector3 scNm    = data.facadeDesign.stringCourseDepth * facadeNormal;
                        Vector3 p0      = data.baseA;
                        Vector3 p1      = data.baseB;
                        Vector3 p0o     = data.baseA - scNm;
                        Vector3 p1o     = data.baseB - scNm;
                        int     submesh = dmesh.submeshLibrary.SubmeshAdd(data.facadeDesign.stringCourseSurface);                                                                                        //data.facadeDesign.stringCourseSurface != null ? facadeSurfaces.IndexOf(data.facadeDesign.stringCourseSurface) : 0;
                        Vector2 uvMax   = new Vector2(facadeLength, data.facadeDesign.stringCourseHeight);
                        dmesh.AddPlane(p0o + scBaseUp, p1o + scBaseUp, p0o + scTopUp, p1o + scTopUp, Vector3.zero, uvMax, -facadeNormal, facadeTangent, submesh, data.facadeDesign.stringCourseSurface); //front
                        dmesh.AddPlane(p0 + scBaseUp, p0o + scBaseUp, p0 + scTopUp, p0o + scTopUp, facadeNormal, facadeTangent, submesh);                                                                //left
                        dmesh.AddPlane(p1o + scBaseUp, p1 + scBaseUp, p1o + scTopUp, p1 + scTopUp, facadeNormal, facadeTangent, submesh);                                                                //right
                        float facadeAngle = BuildrUtils.CalculateFacadeAngle(facadeDirection);
                        dmesh.AddPlaneComplexUp(p0 + scBaseUp, p1 + scBaseUp, p0o + scBaseUp, p1o + scBaseUp, facadeAngle, Vector3.down, facadeTangent, submesh, data.facadeDesign.stringCourseSurface); //bottom
                        dmesh.AddPlaneComplexUp(p1 + scTopUp, p0 + scTopUp, p1o + scTopUp, p0o + scTopUp, facadeAngle, Vector3.up, facadeTangent, submesh, data.facadeDesign.stringCourseSurface);       //top
                    }
                    else
                    {
                        int       baseCurvePointCount = data.anchors.Count;                  //baseCurvepoints.Count;
                        Vector3[] interSectionNmls    = new Vector3[baseCurvePointCount];
                        for (int i = 0; i < baseCurvePointCount - 1; i++)
                        {
                            Vector3 p0 = data.anchors[i].vector3XZ;                            //baseCurvepoints[i];
                            Vector3 p1 = data.anchors[i + 1].vector3XZ;                        //baseCurvepoints[i + 1];
                            Vector3 p2 = data.anchors[Mathf.Max(i - 1, 0)].vector3XZ;          //baseCurvepoints[Mathf.Max(i - 1, 0)];
                            interSectionNmls[i] = Vector3.Cross((p1 - p0 + p0 - p2).normalized, Vector3.up);
                        }

                        for (int i = 0; i < baseCurvePointCount - 1; i++)
                        {
                            Vector3 p0            = data.anchors[i].vector3XZ;                 //baseCurvepoints[i];
                            Vector3 p1            = data.anchors[i + 1].vector3XZ;             //baseCurvepoints[i + 1];
                            Vector3 sectionVector = p1 - p0;
                            Vector3 sectionDir    = sectionVector.normalized;
                            Vector3 sectionNml    = Vector3.Cross(sectionDir, Vector3.up);
                            Vector4 sectionTgnt   = BuildRMesh.CalculateTangent(sectionDir);
                            Vector3 scNmA         = data.facadeDesign.stringCourseDepth * interSectionNmls[i + 0];
                            Vector3 scNmB         = data.facadeDesign.stringCourseDepth * interSectionNmls[i + 1];
                            Vector3 p0o           = p0 - scNmA;
                            Vector3 p1o           = p1 - scNmB;
                            int     submesh       = dmesh.submeshLibrary.SubmeshAdd(data.facadeDesign.stringCourseSurface);                  //data.facadeDesign.stringCourseSurface != null ? facadeSurfaces.IndexOf(data.facadeDesign.stringCourseSurface) : 0;
                            dmesh.AddPlane(p0o + scBaseUp, p1o + scBaseUp, p0o + scTopUp, p1o + scTopUp, sectionNml, sectionTgnt, submesh);
                            dmesh.AddPlane(p0 + scBaseUp, p0o + scBaseUp, p0 + scTopUp, p0o + scTopUp, sectionNml, sectionTgnt, submesh);
                            dmesh.AddPlane(p1o + scBaseUp, p1 + scBaseUp, p1o + scTopUp, p1 + scTopUp, sectionNml, sectionTgnt, submesh);
                            float facadeAngle = BuildrUtils.CalculateFacadeAngle(sectionDir);
                            dmesh.AddPlaneComplexUp(p0 + scBaseUp, p1 + scBaseUp, p0o + scBaseUp, p1o + scBaseUp, facadeAngle, Vector3.down, sectionTgnt, submesh, data.facadeDesign.stringCourseSurface);                      //bottom
                            dmesh.AddPlaneComplexUp(p1 + scTopUp, p0 + scTopUp, p1o + scTopUp, p0o + scTopUp, facadeAngle, Vector3.up, sectionTgnt, submesh, data.facadeDesign.stringCourseSurface);                            //top
                        }
                    }
                }
            }
        }
Esempio n. 19
0
 /// <summary>
 /// tels if a triangle belongs whole to mesh data
 /// </summary>
 /// <param name="triangle"></param>
 /// <param name="data"></param>
 /// <returns></returns>
 public static bool Belongs(this Triangle triangle, RawMeshData data)
 {
     return(data.VertsIndexes.Contains(triangle.P0) && data.VertsIndexes.Contains(triangle.P1) && data.VertsIndexes.Contains(triangle.P2));
 }
Esempio n. 20
0
        //TODO support custom models coming in from roof design
        public static void Generate(ref BuildRMesh mesh, IVolume volume, List <Vector3[]> roofFaces)
        {
            Roof  design     = volume.roof;
            float roofDepth  = design.depth;
            float roofHeight = design.height;

            float dormerWidth  = design.dormerWidth;
            float dormerHeight = design.dormerHeight;
            int   dormerRows   = design.dormerRows;

            if (dormerHeight * dormerRows > roofHeight)
            {
                dormerHeight = roofHeight / dormerRows;
            }
            float dormerRoofHeight = design.dormerRoofHeight;
            float roofPitchRad     = Mathf.Atan2(roofHeight, roofDepth);
            float roofHyp          = Mathf.Sqrt(roofDepth * roofDepth + roofHeight * roofHeight);//todo make a proper calculation - this is incorrect
            float dormerDepth      = Mathf.Cos(roofPitchRad) * dormerHeight;
            float dormerHyp        = Mathf.Sqrt(dormerHeight * dormerHeight + dormerDepth * dormerDepth);
            float dormerRowSpace   = roofHyp / dormerRows;

            dormerHyp = Mathf.Min(dormerHyp, dormerRowSpace);
            float dormerSpace     = dormerRowSpace - dormerHyp;
            float dormerSpaceLerp = dormerSpace / roofHyp;

            if (INTERNAL_B_MESH == null)
            {
                INTERNAL_B_MESH = new BuildRMesh("internal dormer");
            }
            INTERNAL_B_MESH.Clear();

            INTERNAL_B_MESH.submeshLibrary.AddRange(mesh.submeshLibrary.MATERIALS.ToArray());

            Vector3 bpl = Vector3.left * dormerWidth * 0.5f;
            Vector3 bpr = Vector3.right * dormerWidth * 0.5f;
            Vector3 tpc = Vector3.up * dormerHeight;
            float   dormerFaceHeight = dormerHeight - dormerHeight * dormerRoofHeight;
            Vector3 tpl = bpl + Vector3.up * dormerFaceHeight;
            Vector3 tpr = bpr + Vector3.up * dormerFaceHeight;
            Vector3 rpc = tpc + Vector3.back * dormerDepth;
            Vector3 rpl = tpl + Vector3.back * dormerDepth;
            Vector3 rpr = tpr + Vector3.back * dormerDepth;

            Surface mainSurface = design.mainSurface;
            Surface wallSurface = design.wallSurface;
            int     mainSubmesh = mesh.submeshLibrary.SubmeshAdd(mainSurface);
            int     wallSubmesh = mesh.submeshLibrary.SubmeshAdd(wallSurface);

            Vector2 sectionSize = new Vector2(dormerWidth, dormerFaceHeight);

            if (design.wallSection && design.wallSection.CanRender(sectionSize))
            {
                //                mesh.submeshLibrary.Add(design.wallSection);
                mesh.submeshLibrary.Add(design.wallSection);

                GenerationOutput output = GenerationOutput.CreateRawOutput();
                WallSectionGenerator.Generate(design.wallSection, output, sectionSize, false, 0.02f, false, null, mesh.submeshLibrary);
                Vector3 sectionPos = new Vector3(0, dormerFaceHeight * 0.5f, 0);
                int[]   mapping    = new int[output.raw.materials.Count];
                for (int s = 0; s < output.raw.materials.Count; s++)
                {
                    mapping[s] = 0;
                }
                INTERNAL_B_MESH.AddDataKeepSubmeshStructure(output.raw, sectionPos, Quaternion.Euler(0, 180, 0), Vector3.one);
            }
            else
            {
                INTERNAL_B_MESH.AddPlane(bpr, bpl, tpr, tpl, wallSubmesh);//dormer front square
            }

            //front triangle

            INTERNAL_B_MESH.AddTri(tpl, tpr, tpc, Vector3.right, wallSubmesh);
            //roof
            Vector3 normalRoofRight  = Vector3.Cross((tpr - tpc).normalized, (rpc - tpc).normalized);
            Vector4 tangentRoofRight = BuildRMesh.CalculateTangent(Vector3.back);
            Vector3 normalRoofLeft   = Vector3.Cross((rpc - tpc).normalized, (tpl - tpc).normalized);
            Vector4 tangentRoofLeft  = BuildRMesh.CalculateTangent(Vector3.forward);
            Vector2 roofUvMax        = new Vector2(dormerDepth, Vector3.Distance(tpc, tpl));

            INTERNAL_B_MESH.AddPlane(rpr, tpr, rpc, tpc, Vector2.zero, roofUvMax, normalRoofRight, tangentRoofRight, mainSubmesh, mainSurface);
            INTERNAL_B_MESH.AddPlane(rpc, tpc, rpl, tpl, Vector2.zero, roofUvMax, normalRoofLeft, tangentRoofLeft, mainSubmesh, mainSurface);
            //side triangles
            INTERNAL_B_MESH.AddTri(bpr, rpr, tpr, Vector3.back, wallSubmesh);
            INTERNAL_B_MESH.AddTri(bpl, tpl, rpl, Vector3.back, wallSubmesh);

            RawMeshData data = RawMeshData.CopyBuildRMesh(INTERNAL_B_MESH);

            int roofFaceCount = roofFaces.Count;

            for (int r = 0; r < roofFaceCount; r++)
            {
                Vector3[] roofFace = roofFaces[r];
                Vector3   p0       = roofFace[0];
                Vector3   p1       = roofFace[1];
                Vector3   p2       = roofFace[2];
                Vector3   p3       = roofFace[3];

                //center line
                Vector3 pDB             = Vector3.Lerp(p0, p1, 0.5f);
                Vector3 facadeVector    = p1 - p0;
                Vector3 facadeDirection = facadeVector.normalized;
                Vector3 facadeNormal    = Vector3.Cross(Vector3.up, facadeDirection);

                Vector3 projTL = p0 + Vector3.Project(p2 - p0, facadeDirection);
                Vector3 projTR = p1 + Vector3.Project(p3 - p1, facadeDirection);

                float sqrMagP0 = Vector3.SqrMagnitude(p0 - pDB);
                float sqrMagP1 = Vector3.SqrMagnitude(p1 - pDB);
                float sqrMagP2 = Vector3.SqrMagnitude(projTL - pDB);
                float sqrMagP3 = Vector3.SqrMagnitude(projTR - pDB);

                Vector3 dormerBaseLeft  = sqrMagP0 < sqrMagP2 ? p0 : projTL;
                Vector3 dormerBaseRight = sqrMagP1 < sqrMagP3 ? p1 : projTR;

                Vector3 roofNormal = BuildRMesh.CalculateNormal(p0, p2, p1);
                Vector3 roofUp     = Vector3.Cross(roofNormal, -facadeDirection);
                float   actualHyp  = sqrMagP0 < sqrMagP2?Vector3.Distance(p0, p2 + Vector3.Project(p0 - p2, facadeDirection)) : Vector3.Distance(projTL, p2);

                Vector3 dormerTopLeft  = dormerBaseLeft + roofUp * actualHyp;
                Vector3 dormerTopRight = dormerBaseRight + roofUp * actualHyp;

                float topLength       = Vector3.Distance(dormerBaseLeft, dormerBaseRight);
                int   numberOfDormers = Mathf.FloorToInt((topLength - design.minimumDormerSpacing * 2) / (design.minimumDormerSpacing + dormerWidth));

                if (numberOfDormers == 0)
                {
                    if (topLength > sectionSize.x)
                    {
                        numberOfDormers = 1;
                    }
                }

                for (int dr = 0; dr < dormerRows; dr++)
                {
                    float rowPercent = dr / (dormerRows + 0f) + dormerSpaceLerp * 0.5f;
                    //row vector
                    Vector3 rl = Vector3.Lerp(dormerBaseLeft, dormerTopLeft, rowPercent);
                    Vector3 rr = Vector3.Lerp(dormerBaseRight, dormerTopRight, rowPercent);

                    for (int dc = 0; dc < numberOfDormers; dc++)
                    {
                        float   columnPercent = (dc + 1f) / (numberOfDormers + 1f);
                        Vector3 dormerBegin   = Vector3.Lerp(rl, rr, columnPercent);

                        Quaternion meshRot = Quaternion.LookRotation(facadeNormal, Vector3.up);
                        Vector3    meshPos = dormerBegin;
                        //TODO account for the mesh mode of the wall section - custom meshes
                        mesh.AddDataKeepSubmeshStructure(data, meshPos, meshRot, Vector3.one);
                    }
                }
            }
        }
Esempio n. 21
0
 /// <summary>
 /// Copies verts from data prototype by a triangle
 /// </summary>
 /// <param name="triangle"></param>
 /// <param name="data"></param>
 private void CopyMeshValuesByTri(Triangle triangle, RawMeshData data)
 {
     data.Verts.AddRange(data.Prototype.GetVerts(triangle));
     data.Tris.AddLast(new Triangle(data.Verts.Count - 3, data.Verts.Count - 2, data.Verts.Count - 1));
 }
Esempio n. 22
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);
            }
        }
Esempio n. 23
0
 public MeshWithMaterial(RawMeshData meshData, DCVoxelMaterial material, MeshPartRenderData renderData)
 {
     this.meshData   = meshData;
     this.material   = material;
     this.renderData = renderData;
 }