public bool PlanLegalityCheck() { for (int p = 0; p < numberOfPoints; p++) { this[p].illegal = false; } bool output = false; for (int indexAA = 0; indexAA < numberOfPoints; indexAA++) { Vector2Int p0 = _points[indexAA].position; int indexAB = (indexAA + 1) % numberOfPoints; Vector2Int p1 = _points[indexAB].position; for (int indexBA = 0; indexBA < numberOfPoints; indexBA++) { if (indexAA == indexBA) { continue; //skip testing wall on itself } int indexBB = (indexBA + 1) % numberOfPoints; if (indexAA == indexBB) { continue; //skip testing wall on itself } Vector2Int p2 = _points[indexBA].position; Vector2Int p3 = _points[indexBB].position; if (BuildrUtils.PointOnLine(p0, p2, p3)) { _points[indexAA].illegal = true; _points[indexBA].illegal = true; output = true; continue; } if (indexAA == indexBB || indexAB == indexBA || indexAB == indexBB) { continue; //don't test lines that connect } // if (p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3) continue;//don't test lines that connect if (BuildrUtils.FastLineIntersection(p0, p1, p2, p3)) { _points[indexAA].illegal = true; _points[indexBA].illegal = true; output = true; } } } return(output); }
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); }
private bool PlanLegality() { for (int p = 0; p < numberOfPoints; p++) { this[p].illegal = false; } for (int p = 0; p < numberOfPoints - 1; p++) { if (this[p] == this[p + 1]) { _points.RemoveAt(p + 1);//remove duplicate points } } bool output = false; for (int pA = 0; pA < numberOfPoints; pA++) { Vector2Int p0 = _points[pA].position; Vector2Int p1 = _points[(pA + 1) % numberOfPoints].position; for (int pB = 0; pB < numberOfPoints; pB++) { if (pA == pB) { continue; //skip testing wall on itself } Vector2Int p2 = _points[pB].position; Vector2Int p3 = _points[(pB + 1) % numberOfPoints].position; if (p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3) { continue; //don't test lines that connect } if (BuildrUtils.FastLineIntersection(p0, p1, p2, p3)) { _points[pA].illegal = true; _points[pB].illegal = true; output = true; } } } return(output); }
// _drag = Drag2D(_drag, r); // // if (_mPrevRender == null) // _mPrevRender = new PreviewRenderUtility(); // // // Vector3 max = _wallSection.previewMesh.bounds.size; // // float radius = Mathf.Max(max.x, Mathf.Max(max.y, max.z)) * 1.333f; // float dist = radius / (Mathf.Sin(_mPrevRender.camera.fieldOfView * Mathf.Deg2Rad)); // _mPrevRender.camera.transform.position = Vector2.zero; // _mPrevRender.camera.transform.rotation = Quaternion.Euler(new Vector3(-_drag.y, -_drag.x, 0)); // _mPrevRender.camera.transform.position = _mPrevRender.camera.transform.forward * -dist; // _mPrevRender.camera.nearClipPlane = 0.1f; // _mPrevRender.camera.farClipPlane = 500; // // _mPrevRender.lights[0].intensity = 0.5f; // _mPrevRender.lights[0].transform.rotation = Quaternion.Euler(30f, 30f, 0f); // _mPrevRender.lights[1].intensity = 0.5f; // // _mPrevRender.BeginPreview(r, background); // // if (_plane != null && _blueprintMaterial != null) // { // Matrix4x4 matrix = Matrix4x4.TRS(new Vector3(-25, -25, 1), Quaternion.identity, new Vector3(10, 10, 1)); // _mPrevRender.DrawMesh(_plane, matrix, _blueprintMaterial, 0); // _mPrevRender.camera.Render(); // } // // // int materialCount = mats.Length; // int submeshCount = mesh.subMeshCount; // int count = Mathf.Min(materialCount, submeshCount); // for (int c = 0; c < count; c++) // { // Material mat = c < materialCount ? mats[c] : AssetDatabase.GetBuiltinExtraResource<Material>("Default-Material.mat"); // if (mat == null) mat = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Material.mat"); // _mPrevRender.DrawMesh(mesh, Matrix4x4.identity, mat, c); // } // // _mPrevRender.camera.Render(); // Texture texture = _mPrevRender.EndPreview(); // // GUI.DrawTexture(r, texture); // } // // public static Vector2 Drag2D(Vector2 scrollPosition, Rect position) // { // int controlID = GUIUtility.GetControlID("Slider".GetHashCode(), FocusType.Passive); // Event current = Event.current; // switch (current.GetTypeForControl(controlID)) // { // case EventType.MouseDown: // if (position.Contains(current.mousePosition) && position.width > 50f) // { // GUIUtility.hotControl = controlID; // current.Use(); // EditorGUIUtility.SetWantsMouseJumping(1); // } // break; // case EventType.MouseUp: // if (GUIUtility.hotControl == controlID) // { // GUIUtility.hotControl = 0; // } // EditorGUIUtility.SetWantsMouseJumping(0); // break; // case EventType.MouseDrag: // if (GUIUtility.hotControl == controlID) // { // scrollPosition -= current.delta * (float)((!current.shift) ? 1 : 3) / Mathf.Min(position.width, position.height) * 140f; // scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f); // current.Use(); // GUI.changed = true; // } // break; // } // return scrollPosition; // } public static FloorplanClick OnInteriorSelectionClick(Ray mouseRay) { FloorplanClick output = new FloorplanClick(); Building building = BuildingEditor.building; Volume volume = BuildingEditor.volume; Floorplan floorplan = BuildingEditor.floorplan; output.volume = volume; output.floorplan = floorplan; if (floorplan != null) { Vector3 basePosition = building.transform.position; float baseHeight = volume.baseHeight; Vector3 testPoint = basePosition + Vector3.up * baseHeight; if (Vector3.Dot(mouseRay.direction, testPoint - mouseRay.origin) < 0)//volume behind camera { return(output); } float floorHeight = volume.floorHeight; List <Room> rooms = floorplan.rooms; int roomCount = rooms.Count; float minDistance = Mathf.Infinity; for (int rm = 0; rm < roomCount; rm++) { Room room = rooms[rm]; RoomPortal[] portals = room.GetAllPortals(); int portalCount = portals.Length; for (int p = 0; p < portalCount; p++) { RoomPortal portal = portals[p]; int wallIndex = portal.wallIndex; Vector3 p0 = room[wallIndex].position.vector3XZ; Vector3 p1 = room[(wallIndex + 1) % room.numberOfPoints].position.vector3XZ; Vector3 baseUp = Vector3.up * (floorHeight - portal.height) * portal.verticalPosition; Vector3 portalUp = baseUp + Vector3.up * portal.height; Vector3 pointPos = SceneMeshHandler.PortalPosition(Quaternion.identity, room, portal); pointPos.y = baseHeight; Vector3 wallDirection = (p1 - p0).normalized; float defaultWidth = portal.width * 0.5f; // float defaultDepth = 0.1f; Vector3 v0 = pointPos - wallDirection * defaultWidth; Vector3 v1 = pointPos + wallDirection * defaultWidth; Vector3 v2 = v0 + portalUp; Vector3 v3 = v1 + portalUp; // Debug.DrawLine(v0,v1,Color.red,20); // Debug.DrawLine(v1,v3,Color.red,20); // Debug.DrawLine(v3,v2,Color.red,20); // Debug.DrawLine(v2,v0,Color.red,20); float distance = 0; if (RayTriangle.QuadIntersection(v0, v1, v2, v3, mouseRay, out distance, false)) { if (minDistance > distance) { minDistance = distance; output.room = room; output.portal = portal; output.opening = null; } } } } VerticalOpening[] openings = building.GetAllOpenings(); int openingCount = openings.Length; for (int o = 0; o < openingCount; o++) { VerticalOpening opening = openings[o]; Vector3 openingPosition = opening.position.vector3XZ; openingPosition.y = volume.floorHeight * opening.baseFloor; Vector3 openingSize = opening.size.vector3XZ; float openingWidth = openingSize.x; float openingHeight = openingSize.z; Quaternion openingRotation = Quaternion.Euler(0, opening.rotation, 0); Vector3 p0 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, -openingHeight) * 0.5f; Vector3 p1 = openingPosition + openingRotation * new Vector3(openingWidth, 0, -openingHeight) * 0.5f; Vector3 p2 = openingPosition + openingRotation * new Vector3(openingWidth, 0, openingHeight) * 0.5f; Vector3 p3 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, openingHeight) * 0.5f; // Vector3 openingUp = Vector3.up * volume.floorHeight * (opening.floors + 1); Vector3 floorUpA = Vector3.up * volume.CalculateFloorHeight(volume.Floor(BuildingEditor.floorplan)); // Vector3 floorUpB = floorUpA + Vector3.up * volume.floorHeight; float distance = 0; if (RayTriangle.QuadIntersection(p0 + floorUpA, p1 + floorUpA, p2 + floorUpA, p3 + floorUpA, mouseRay, out distance, false)) { if (minDistance > distance) { minDistance = distance; output.room = null; output.portal = null; output.opening = opening; } } } if (output.opening != null) { return(output); } if (output.portal != null) { return(output); } float intPlanBaseHeight = volume.CalculateFloorHeight(volume.Floor(floorplan)); Vector3 baseUpV = Vector3.up * intPlanBaseHeight; Plane planPlane = new Plane(Vector3.up, baseUpV); float rayDistance = 0; if (planPlane.Raycast(mouseRay, out rayDistance)) { Vector3 clickPos = mouseRay.GetPoint(rayDistance) - basePosition; Vector2Int floorClickPosition = new Vector2Int(clickPos, true); for (int rm = 0; rm < roomCount; rm++) { Vector2Int[] roomPoints = rooms[rm].AllPoints(); if (BuildrUtils.PointInsidePoly(floorClickPosition, roomPoints)) { output.room = rooms[rm]; } } } } return(output); }
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 } } } } }
public static void Generate(IBuilding building) { int numberOfVolumes = building.numberOfVolumes; // Debug.Log("n vol "+numberOfVolumes); for (int v = 0; v < numberOfVolumes; v++) { IVolume volume = building[v]; volume.CheckVolume(); if (!volume.isLegal) { GenerateMesh.ClearVisuals(volume); continue; } int numberOfPoints = volume.numberOfPoints; float totalPlanHeight = volume.planHeight; Vector3 planUp = totalPlanHeight * Vector3.up; VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume); float foundation = building.IsBaseVolume(volume) ? building.foundationDepth : 0;//set suspended volumes foundation to 0 IVisualPart visual = volume.visualPart; BuildRMesh dMesh = visual.dynamicMesh; BuildRCollider cMesh = visual.colliderMesh; BuildingMeshTypes meshType = building.meshType; BuildingColliderTypes colliderType = building.colliderType; dMesh.Clear(); cMesh.Clear(); cMesh.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive); cMesh.thickness = volume.wallThickness; if (colliderType == BuildingColliderTypes.None) { cMesh = null; } Transform[] prefabs = volume.prefabs.GetComponentsInChildren <Transform>(); int prefabCount = prefabs.Length; for (int p = 0; p < prefabCount; p++) { if (prefabs[p] == volume.prefabs) { continue; } if (prefabs[p] == null) { continue; //gone already man } #if UNITY_EDITOR Object.DestroyImmediate(prefabs[p].gameObject); #else Object.Destroy(prefabs[p].gameObject); #endif } Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors; Texture2D facadeTexture = null; #region Exteriors // Debug.Log("ext"); if (building.generateExteriors) { for (int p = 0; p < numberOfPoints; p++) { if (!volume[p].render) { continue; } Vector3 p0 = volume.BuildingPoint(p); Vector3 p1 = volume.BuildingPoint((p + 1) % numberOfPoints); Vector3 p0u = p0 + planUp; Vector3 p1u = p1 + planUp; Vector3 cw0 = volume.BuildingControlPointA(p); Vector3 cw1 = volume.BuildingControlPointB(p); Facade facade = volume.GetFacade(p); bool isStraight = volume.IsWallStraight(p); Vector3 facadeVector = p1 - p0; Vector3 facadeDirection = facadeVector.normalized; float facadeLength = facadeVector.magnitude; if (facadeLength < Mathf.Epsilon) { continue; } // Debug.Log("flength "+facadeLength); if (facade == null || colliderType == BuildingColliderTypes.Simple) { // Debug.Log("simple"); if (isStraight) { Vector3 normal = Vector3.Cross(Vector3.up, facadeDirection); Vector4 tangent = BuildRMesh.CalculateTangent(facadeDirection); if (facade == null) { dMesh.AddPlane(p0, p1, p0u, p1u, normal, tangent, 0); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(p0, p1, p0u, p1u); } if (foundation > Mathf.Epsilon) { Vector3 fp2 = p0; Vector3 fp3 = p1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (facade == null) { Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null; int foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface); Vector2 uxmax = new Vector2(Vector3.Distance(p0, p1), foundation); dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface); } if (colliderType != BuildingColliderTypes.None) { cMesh.mesh.AddPlane(fp0, fp1, fp2, fp3, 0); } } } else { List <Vector2Int> facadeAnchorPoints = anchorPoints[p]; int anchorCount = facadeAnchorPoints.Count; for (int i = 0; i < anchorCount - 1; i++) { Vector3 c0 = facadeAnchorPoints[i].vector3XZ; c0.y = p0.y; Vector3 c1 = facadeAnchorPoints[i + 1].vector3XZ; c1.y = p0.y; Vector3 c2 = c0 + planUp; Vector3 c3 = c1 + planUp; Vector3 sectionDirection = (c1 - c0).normalized; Vector3 normal = Vector3.Cross(Vector3.up, sectionDirection); Vector4 tangent = BuildRMesh.CalculateTangent(sectionDirection); if (facade == null) { dMesh.AddPlane(c0, c1, c2, c3, normal, tangent, 0); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(c0, c1, c2, c3); } if (foundation > Mathf.Epsilon) { Vector3 fp2 = c0; Vector3 fp3 = c1; Vector3 fp0 = fp2 + Vector3.down * foundation; Vector3 fp1 = fp3 + Vector3.down * foundation; if (facade == null) { Surface foundationSurface = building.foundationSurface != null ? building.foundationSurface : null; int foundationSubmesh = dMesh.submeshLibrary.SubmeshAdd(foundationSurface); Vector2 uxmax = new Vector2(Vector3.Distance(c0, c1), foundation); dMesh.AddPlane(fp0, fp1, fp2, fp3, Vector2.zero, uxmax, normal, tangent, foundationSubmesh, foundationSurface); } if (colliderType != BuildingColliderTypes.None) { cMesh.AddPlane(fp0, fp1, fp2, fp3); } } } } // Debug.Log("Generate facade " + p + " " + dMesh.vertexCount ); } // Debug.Log("fac "+p); if (facade != null && (meshType == BuildingMeshTypes.Full || colliderType == BuildingColliderTypes.Primitive || colliderType == BuildingColliderTypes.Complex)) { //generate the facade // Debug.Log("full"); FacadeGenerator.FacadeData fData = new FacadeGenerator.FacadeData(); // fData.building = building; // fData.volume = volume; fData.baseA = p0; fData.baseB = p1; fData.controlA = cw0; fData.controlB = cw1; fData.anchors = anchorPoints[p]; fData.isStraight = isStraight; fData.curveStyle = volume[p].curveStyle; fData.floorCount = volume.floors; fData.facadeDesign = facade; // fData.submeshList = usedFloorplanSurfaces; fData.startFloor = BuildRFacadeUtil.MinimumFloor(building, volume, p); fData.actualStartFloor = building.VolumeBaseFloor(volume); fData.foundationDepth = foundation; fData.foundationSurface = building.foundationSurface; fData.wallThickness = volume.wallThickness; fData.minimumWallUnitLength = volume.minimumWallUnitLength; fData.floorHeight = volume.floorHeight; fData.floors = volume.floors; fData.meshType = building.meshType; fData.colliderType = building.colliderType; fData.cullDoors = building.cullDoors; fData.prefabs = volume.prefabs; // Debug.Log("mesh"); FacadeGenerator.GenerateFacade(fData, dMesh, cMesh); // Debug.Log("pref"); FacadeGenerator.GeneratePrefabs(fData); // Debug.Log("Generate facade "+p+" "+dMesh.vertexCount); } } } #endregion #region Interiors // Debug.Log("int"); bool generateInteriors = building.generateInteriors && meshType == BuildingMeshTypes.Full; if (generateInteriors) { int floors = volume.floors; IFloorplan[] floorplans = volume.InteriorFloorplans(); for (int fl = 0; fl < floors; fl++) { IFloorplan floorplan = floorplans[fl]; IVisualPart floorVisual = floorplan.visualPart; BuildRMesh flMesh = floorVisual.dynamicMesh; BuildRCollider flCollider = floorVisual.colliderMesh; flMesh.Clear(); flCollider.Clear(); flCollider.TogglePrimitives(colliderType == BuildingColliderTypes.Primitive); FloorplanGenerator.Generate(building, volume, floorplans[fl], fl, volumeOpenings, flMesh, flCollider); floorVisual.GenerateFromDynamicMesh(); floorplan.transform.localPosition = Vector3.up * (fl * volume.floorHeight); floorVisual.transform.localPosition = Vector3.zero;// floorVisual.transform.localRotation = Quaternion.identity; } } else { IFloorplan[] floorplans = volume.InteriorFloorplans(); int floors = floorplans.Length; for (int fl = 0; fl < floors; fl++) { floorplans[fl].visualPart.Clear(); } } #endregion #region Volume Underside Generation // Debug.Log("und"); BuildRVolumeUtil.VolumeShape[] underShapes = BuildRVolumeUtil.GetBottomShape(building, volume); int underShapeCount = underShapes.Length; float volumeBaseHeight = volume.baseHeight - building.foundationDepth; for (int u = 0; u < underShapeCount; u++) { if (underShapes[u].outer == null) { continue; //no underside shape } int undersideSubmesh = dMesh.submeshLibrary.SubmeshAdd(volume.undersideSurafce); Poly2TriWrapper.BMesh(dMesh, volumeBaseHeight, null, undersideSubmesh, underShapes[u].outer, new Rect(0, 0, 0, 0), false, underShapes[u].holes); } #endregion // Debug.Log("roof"); if (building.generateExteriors) { RoofGenerator.Generate(building, volume, dMesh, cMesh); visual.GenerateFromDynamicMesh(); } else { visual.Clear(); } // Debug.Log("mat"); switch (meshType) { case BuildingMeshTypes.None: visual.materials = null; break; case BuildingMeshTypes.Box: visual.materials = new[] { new Material(Shader.Find("Standard")) }; break; case BuildingMeshTypes.Simple: facadeTexture.filterMode = FilterMode.Bilinear; facadeTexture.Apply(true, false); Material simpleMaterial = new Material(Shader.Find("Standard")); simpleMaterial.mainTexture = facadeTexture; visual.materials = new[] { simpleMaterial }; break; case BuildingMeshTypes.Full: visual.materials = dMesh.materials.ToArray(); break; } } }
public static VolumeShape[] GetTopShape(IBuilding building, IVolume volume, Vector2[] usePoints = null) { VolumeShape[] output; Clipper clipper = new Clipper(); Paths subj = new Paths(); if (usePoints == null) { subj.Add(VolumeToPath(volume)); } else { subj.Add(Vector2ToPath(usePoints)); } Paths clip = new Paths(); int numberOfAbovePlans = volume.abovePlanCount; Vector2[][] aboveVolumeShapes = new Vector2[numberOfAbovePlans][]; for (int op = 0; op < numberOfAbovePlans; op++) { if (volume.AbovePlanList()[op] == null) { continue; } aboveVolumeShapes[op] = volume.AbovePlanList()[op].AllPointsV2(); clip.Add(Vector2ToPath(aboveVolumeShapes[op])); } VerticalOpening[] volumeOpenings = BuildrUtils.GetOpeningsQuick(building, volume); int numberOfOpenings = volumeOpenings.Length; int volumeTopFloor = volume.floors + building.VolumeBaseFloor(volume); for (int op = 0; op < numberOfOpenings; op++) { if (!volumeOpenings[op].FloorIsIncluded(volumeTopFloor)) { continue; } bool isInOtherVolume = false; Vector2[] openingPoints = volumeOpenings[op].Points(); int openingSize = openingPoints.Length; for (int v = 0; v < numberOfAbovePlans; v++) { if (volume.AbovePlanList()[v] == null) { continue; } for (int p = 0; p < openingSize; p++) { if (PointInPolygon(openingPoints[p], aboveVolumeShapes[v])) { isInOtherVolume = true; break; } } if (isInOtherVolume) { break; } } if (!isInOtherVolume) { clip.Add(OpeningToPath(volumeOpenings[op])); } } if (clip.Count > 0) { PolyTree pTree = new PolyTree(); clipper.AddPaths(subj, PolyType.ptSubject, true); clipper.AddPaths(clip, PolyType.ptClip, true); clipper.Execute(ClipType.ctDifference, pTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero); int shapeCount = pTree.ChildCount; // Debug.Log("GetTopShape "+shapeCount); output = new VolumeShape[shapeCount]; for (int s = 0; s < shapeCount; s++) { PolyNode node = pTree.Childs[s]; output[s] = new VolumeShape(); output[s].outer = PathToVector2(node.Contour); int holeCount = node.ChildCount; output[s].holes = new Vector2[holeCount][]; for (int h = 0; h < holeCount; h++) { PolyNode holeNode = node.Childs[h]; output[s].holes[h] = PathToVector2(holeNode.Contour); } } } else { output = new VolumeShape[1]; output[0] = new VolumeShape(); output[0].outer = usePoints; output[0].holes = new Vector2[0][]; } SplitSelfIntersecting(output); return(output); }
public static void OnSceneGUI(Building _building) { Vector3 position = _building.transform.position; // Quaternion rotation = _building.transform.rotation; bool shiftIsDown = Event.current.shift; // bool controlIsDown = Event.current.control; // bool altIsDown = Event.current.alt; // Camera sceneCamera = Camera.current; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);//sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0)); Event current = Event.current; IVolume mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray).volume; // Volume clickedPlan = null; switch (current.type) { case EventType.MouseMove: SceneView.RepaintAll(); break; case EventType.MouseDown: // if (current.button == 0) // clickedPlan = mouseOverPlan; break; case EventType.ScrollWheel: break; } Vector3 basePosition = position; if (BuildingEditor.volume != null) { basePosition += BuildingEditor.volume.baseHeight * Vector3.up; } Plane buildingPlane = new Plane(Vector3.up, basePosition); Vector3 mousePlanePoint = Vector3.zero; float mouseRayDistance; if (buildingPlane.Raycast(ray, out mouseRayDistance)) { mousePlanePoint = ray.GetPoint(mouseRayDistance); } if (shiftIsDown) { mousePlanePoint.x = Mathf.Round(mousePlanePoint.x); mousePlanePoint.y = Mathf.Round(mousePlanePoint.y); mousePlanePoint.z = Mathf.Round(mousePlanePoint.z); } // float mouseHandleSize = HandleUtility.GetHandleSize(mousePlanePoint) * 0.2f; DrawFloorplans(_building, mouseOverPlan); // if (clickedPlan != null && clickedPlan != SELECTED_VOLUME) // { // SELECTED_VOLUME = clickedPlan; // Repaint(); // current.Use(); // } }
private static void DrawFloorplans(IBuilding _building, IVolume mouseOverPlan) { int numberOfFloorplans = _building.numberOfPlans; Vector3 position = _building.transform.position; Quaternion rotation = _building.transform.rotation; Camera sceneCamera = Camera.current; Vector3[] centerPoints = new Vector3[numberOfFloorplans]; for (int f = 0; f < numberOfFloorplans; f++) { centerPoints[f] = BuildrUtils.CalculateFloorplanCenter(_building[f]); } // Ray ray = sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0)); // Floorplan mouseOverPlan = BuildrUtils.OnFloorplanSelectionClick(_building, ray); //Draw Floorplan outlines for (int f = 0; f < numberOfFloorplans; f++) { IVolume volume = _building[f]; int numberOfPoints = volume.numberOfPoints; Vector2 leftPoint = Vector2.right; Vector3 labelPoint = volume.BuildingPoint(0) + position; int numberOfTopPoints = 0; for (int p = 0; p < numberOfPoints; p++) { if (volume.IsWallStraight(p)) { numberOfTopPoints++; } else { numberOfTopPoints += 9; } } Vector3[] planVs = new Vector3[numberOfTopPoints]; int planVIndex = 0; Vector3 planUp = Vector3.up * volume.planHeight; for (int p = 0; p < numberOfPoints; p++) { Vector3 p0 = volume.WorldPoint(p) + planUp;//rotation * floorplan.BuildingPoint(p) + position); Vector2 p0ss = sceneCamera.WorldToScreenPoint(p0); if (p0ss.x < leftPoint.x) { leftPoint = p0ss; labelPoint = p0; } //Render handles if (volume.IsWallStraight(p)) { planVs[planVIndex] = p0; planVIndex++; } else { Vector3 p1 = volume.WorldPoint((p + 1) % numberOfPoints) + planUp; //rotation * floorplan.BuildingPoint((p + 1) % numberOfPoints) + position); Vector3 cw0 = volume.WorldControlPointA(p) + planUp; //rotation * floorplan.BuildingControlPoint(p) + position); Vector3 cw1 = volume.WorldControlPointB(p) + planUp; //rotation * floorplan.BuildingControlPoint(p) + position); Vector3[] curveWall = new Vector3[10]; for (int t = 0; t < 10; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); curveWall[t] = cp; if (t < 9) { planVs[planVIndex] = cp; planVIndex++; } } } } if ((Volume)volume == BuildingEditor.volume) { Handles.color = SELECTED_BLUEPRINT_COLOUR; } else if (mouseOverPlan == volume) { Handles.color = HIGHLIGHTED_BLUEPRINT_COLOUR; } else { Handles.color = UNSELECTED_BLUEPRINT_COLOUR; } // Handles.DrawAAConvexPolygon(planVs);//draw plan outline DrawConcavePolygonHandle.Shape(planVs, Handles.color); // Vector2 textDimensions = GUI.skin.label.CalcSize(new GUIContent(volume.name)); Handles.Label(labelPoint, volume.name); int linkCount = volume.linkPlanCount; Vector3 thisCenter = centerPoints[f]; Handles.color = Color.green; for (int l = 0; l < linkCount; l++) { if (f == l) { continue; } // Volume link = volume.linkedPlans[l]; Vector3 linkCenter = centerPoints[l]; Handles.DrawDottedLine(thisCenter, linkCenter, 5); } int numberOfFloors = volume.floors; float planHeight = volume.floorHeight; float totalPlanHeight = volume.planHeight; Vector3 planHeightV = totalPlanHeight * Vector3.up; Handles.color = new Color(0, 0.2f, 1, 0.5f); for (int p = 0; p < numberOfPoints; p++) { Vector3 p0 = rotation * volume.BuildingPoint(p) + position; Vector3 p1 = rotation * volume.BuildingPoint((p + 1) % numberOfPoints) + position; //Render handles if (volume.IsWallStraight(p)) { int wallSections = Mathf.FloorToInt(Vector3.Distance(p0, p1) / volume.minimumWallUnitLength); if (wallSections < 1) { wallSections = 1; } for (int ws = 0; ws < wallSections + 1; ws++) { float lerp = ws / ((float)wallSections); Vector3 basePos = Vector3.Lerp(p0, p1, lerp); Handles.DrawLine(basePos, basePos + planHeightV); } for (int fl = 0; fl < numberOfFloors + 1; fl++) { Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } else { Vector3 cw0 = volume.WorldControlPointA(p); Vector3 cw1 = volume.WorldControlPointB(p); Vector3[] curveWall = new Vector3[10]; float arcLength = 0; for (int t = 0; t < 10; t++) { Vector3 cp = FacadeSpline.Calculate(p0, cw0, cw1, p1, t / 9f); curveWall[t] = cp; if (t > 0) { arcLength += Vector3.Distance(curveWall[t - 1], curveWall[t]); } } for (int fl = 0; fl < numberOfFloors + 1; fl++) { Handles.color = fl == 0 || fl == numberOfFloors ? MAIN_LINE_COLOUR : SUB_LINE_COLOUR; float lineHeight = fl * planHeight; Vector3 lineHeightV = lineHeight * Vector3.up; for (int t = 0; t < 9; t++) { Vector3 cwp0 = curveWall[t]; Vector3 cwp1 = curveWall[t + 1]; Handles.DrawLine(cwp0 + lineHeightV, cwp1 + lineHeightV); } // Handles.DrawLine(p0 + lineHeightV, p1 + lineHeightV); } } Handles.color = MAIN_LINE_COLOUR; Handles.DrawLine(p0, p0 + Vector3.up * totalPlanHeight); if ((Volume)volume == BuildingEditor.volume) { Vector3 facadeCenter = Vector3.Lerp(p0, p1, 0.5f) + planUp; // float gtbSize = HandleUtility.GetHandleSize(facadeCenter) * 0.1f; // Handles.Label(facadeCenter, "Is gabled"); // Handles.Button(facadeCenter, Quaternion.identity, gtbSize, gtbSize, Handles.DotCap); Handles.BeginGUI(); Vector2 portalScreenPos = Camera.current.WorldToScreenPoint(facadeCenter); portalScreenPos.y = Camera.current.pixelHeight - portalScreenPos.y; Rect screenRect = new Rect(portalScreenPos, new Vector2(350, 500)); GUILayout.BeginArea(screenRect); EditorGUILayout.LabelField(string.Format("Facade: {0}", p + 1)); // RoofFacadeInspectorGUI(volume, p); GUILayout.EndArea(); Handles.EndGUI(); } } } }
public static void BuildFloorplan() { LAYERS.Clear(); SceneMeshLayer layerOpengings = new SceneMeshLayer(); SceneMeshLayer layer0 = new SceneMeshLayer(); SceneMeshLayer layer1 = new SceneMeshLayer(); SceneMeshLayer layer2 = new SceneMeshLayer(); LAYERS.Add(layerOpengings); LAYERS.Add(layer0); LAYERS.Add(layer1); LAYERS.Add(layer2); Building building = BuildingEditor.building; bPosition = building.transform.position; bRotation = building.transform.rotation; BuildRSettings settings = building.settings; int numberOfVolumes = building.numberOfPlans; Quaternion rotation = building.transform.rotation; Vector3[] centerPoints = new Vector3[numberOfVolumes]; for (int f = 0; f < numberOfVolumes; f++) { centerPoints[f] = BuildrUtils.CalculateFloorplanCenter(building[f]); } for (int v = 0; v < numberOfVolumes; v++) { Volume volume = (Volume)building[v]; bool isSelectedVolume = BuildingEditor.volume == volume; int numberOfPoints = volume.numberOfPoints; Vector3 vUp = Vector3.up * volume.floorHeight; Dictionary <int, List <Vector2Int> > anchorPoints = volume.facadeWallAnchors; IFloorplan[] floorplans = volume.InteriorFloorplans(); int floorplanCount = floorplans.Length; for (int f = 0; f < floorplanCount; f++)//floors { IFloorplan floorplan = floorplans[f]; bool isSelectedFloorplan = BuildingEditor.floorplan == (Floorplan)floorplan; float intPlanBaseHeight = volume.CalculateFloorHeight(f); Vector3 baseUpV = Vector3.up * intPlanBaseHeight; //draw external outline of selected floor if (numberOfPoints > 0 && isSelectedVolume) { SceneMeshLayer useLayer = isSelectedFloorplan ? layer1 : layer0; List <Vector2Int> planVs = new List <Vector2Int>(); Color fillCol = settings.subLineColour; Color lineCol = settings.mainLineColour; for (int p = 0; p < numberOfPoints; p++) { if (volume.IsWallStraight(p)) { if (!planVs.Contains(volume[p].position)) { planVs.Add(volume[p].position); } Vector3 p0 = volume[p].position.vector3XZ + baseUpV; Vector3 p1 = volume[(p + 1) % numberOfPoints].position.vector3XZ + baseUpV; Vector3 p2 = p0 + vUp; Vector3 p3 = p1 + vUp; useLayer.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p3, p2)); useLayer.lines.Add(new SceneMeshLine(p2, p3, lineCol)); useLayer.lines.Add(new SceneMeshLine(p0, p2, lineCol)); useLayer.lines.Add(new SceneMeshLine(p1, p3, lineCol)); if (isSelectedFloorplan) { useLayer.lines.Add(new SceneMeshLine(p0, p1, Color.red)); List <Vector2Int> anchors = anchorPoints[p]; int wallSections = anchors.Count; for (int w = 0; w < wallSections - 1; w++) { Vector3 a = anchors[w].vector3XZ + baseUpV; float anchorSize = 0.05f; if (w == 0) { anchorSize *= 2; } useLayer.dots.Add(new SceneMeshDot(a, anchorSize, settings.anchorColour)); } } } else { List <Vector2Int> anchors = anchorPoints[p]; int wallSections = anchors.Count; for (int w = 0; w < wallSections - 2; w++) { if (!planVs.Contains(anchors[w])) { planVs.Add(anchors[w]); } Vector3 p0 = anchors[w].vector3XZ + baseUpV; Vector3 p1 = anchors[w + 1].vector3XZ + baseUpV; Vector3 p2 = p0 + vUp; Vector3 p3 = p1 + vUp; useLayer.lines.Add(new SceneMeshLine(p2, p3, lineCol)); if (w == 0) { useLayer.lines.Add(new SceneMeshLine(p0, p2, lineCol)); } if (w == wallSections - 2) { useLayer.lines.Add(new SceneMeshLine(p1, p3, lineCol)); } useLayer.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p3, p2)); if (isSelectedFloorplan) { useLayer.lines.Add(new SceneMeshLine(p0, p1, Color.red)); float anchorSize = 0.05f; if (w == 0) { anchorSize *= 2; } if (w < wallSections - 1) { useLayer.dots.Add(new SceneMeshDot(p0, anchorSize, settings.anchorColour)); } } } } } if (isSelectedFloorplan) { int planVCount = planVs.Count; Vector3[] planV3 = new Vector3[planVCount]; for (int pv = 0; pv < planVCount; pv++) { planV3[pv] = planVs[pv].vector3XZ + baseUpV; } ShapeWithLines(useLayer, planV3, Color.red, new Color(1, 1, 1, 0.9f)); } } if (isSelectedFloorplan) { Room[] rooms = floorplan.AllRooms(); int roomCount = rooms.Length; List <Vector2Int> shapePoints = new List <Vector2Int>(); for (int r = 0; r < roomCount; r++) { Room room = rooms[r]; bool isRoomSelected = room == BuildingEditor.room && BuildingEditor.roomPortal == null && BuildingEditor.opening == null; shapePoints.Clear(); FloorplanUtil.RoomWall[] roomWalls = FloorplanUtil.CalculatePoints(room, volume); int roomWallCount = roomWalls.Length; Color wallCol = isRoomSelected ? settings.roomWallSelectedColour : settings.roomWallColour; Color floorCol = isRoomSelected ? settings.roomWallSelectedColour : settings.roomFloorColour; Color mainLineCol = isRoomSelected ? settings.selectedPointColour : settings.mainLineColour; Color subLineCol = isRoomSelected ? settings.selectedPointColour : settings.subLineColour; for (int rwp = 0; rwp < roomWallCount; rwp++) { FloorplanUtil.RoomWall roomWall = roomWalls[rwp]; int offsetCount = roomWall.offsetPoints.Length; Vector2Int pi0 = roomWall.baseA; Vector2Int pi1 = roomWall.baseB; if (pi0 == pi1) { continue; //not a wall } for (int op = 0; op < offsetCount - 1; op++) { Vector2Int wsint0 = new Vector2Int(roomWall.offsetPoints[op]); if (!shapePoints.Contains(wsint0)) { shapePoints.Add(wsint0); } Vector3 ws0 = new Vector3(roomWall.offsetPoints[op].x, 0, roomWall.offsetPoints[op].y) + baseUpV; if (isSelectedFloorplan)//draw anchor points { float anchorSize = 0.05f; if (op == 0) { anchorSize *= 2; } layer1.dots.Add(new SceneMeshDot(ws0, anchorSize * 0.05f, settings.linkedAnchorColour)); } int nextIndex = (op + 1) % offsetCount; Vector3 ws1 = new Vector3(roomWall.offsetPoints[nextIndex].x, 0, roomWall.offsetPoints[nextIndex].y) + baseUpV; Vector3 ws2 = ws0 + vUp; Vector3 ws3 = ws1 + vUp; layer1.lines.Add(new SceneMeshLine(ws0, ws1, mainLineCol)); layer1.lines.Add(new SceneMeshLine(ws0, ws2, subLineCol)); layer1.lines.Add(new SceneMeshLine(ws1, ws3, subLineCol)); layer1.shapes.Add(new SceneMeshShape(wallCol, ws0, ws1, ws3, ws2)); } } int shapePointsCount = shapePoints.Count; Vector3[] planV3 = new Vector3[shapePointsCount]; for (int pv = 0; pv < shapePointsCount; pv++) { planV3[pv] = shapePoints[pv].vector3XZ + baseUpV; } ShapeWithLines(layer1, planV3, mainLineCol, floorCol, settings.highlightPerpendicularity, settings.highlightPerpendicularityColour, settings.highlightAngleColour); RoomPortal[] portals = room.GetAllPortals(); int portalCount = portals.Length; for (int pt = 0; pt < portalCount; pt++) { RoomPortal portal = portals[pt]; bool isSelected = BuildingEditor.roomPortal == portal; Color portalLineColour = isSelectedFloorplan ? settings.mainLineColour : settings.subLineColour; Color portalFillColour = isSelected ? settings.selectedPointColour : settings.mainLineColour; if (!isSelectedFloorplan) { portalFillColour = Color.clear; } DrawPortal(layer2, rotation, intPlanBaseHeight, volume.floorHeight, room, portal, portalLineColour, portalFillColour); } } for (int r = 0; r < roomCount; r++) { Room room = rooms[r]; Vector3 roomCenter = room.center.vector3XZ + baseUpV + Vector3.up * volume.floorHeight; layer1.labels.Add(new SceneMeshLabel(roomCenter, string.Format("Room {0}", (r + 1)))); } } //Draw vertical openings if (BuildingEditor.floorplan != null) { VerticalOpening[] openings = building.GetAllOpenings(); int openingCount = openings.Length; for (int o = 0; o < openingCount; o++) { VerticalOpening opening = openings[o]; bool isSelectedOpening = BuildingEditor.opening == opening; Vector3 openingPosition = opening.position.vector3XZ; openingPosition.y = volume.floorHeight * opening.baseFloor; Vector3 openingSize = opening.size.vector3XZ; float openingWidth = openingSize.x; float openingHeight = openingSize.z; Quaternion openingRotation = Quaternion.Euler(0, opening.rotation, 0); Vector3 p0 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, -openingHeight) * 0.5f; Vector3 p1 = openingPosition + openingRotation * new Vector3(openingWidth, 0, -openingHeight) * 0.5f; Vector3 p2 = openingPosition + openingRotation * new Vector3(openingWidth, 0, openingHeight) * 0.5f; Vector3 p3 = openingPosition + openingRotation * new Vector3(-openingWidth, 0, openingHeight) * 0.5f; Vector3 openingUp = Vector3.up * volume.floorHeight * (opening.floors + 1); //"Phil" Mitchels Color fillCol = settings.subLineColour; fillCol.a = 0.05f; layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p2, p3)); layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p0, p1, p1 + openingUp, p0 + openingUp)); layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p1, p2, p2 + openingUp, p1 + openingUp)); layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p2, p3, p3 + openingUp, p2 + openingUp)); layerOpengings.shapes.Add(new SceneMeshShape(fillCol, p3, p0, p0 + openingUp, p3 + openingUp)); //lines Color lineCol = settings.invertLineColour; layer0.lines.Add(new SceneMeshLine(p0, p1, lineCol)); layer0.lines.Add(new SceneMeshLine(p1, p2, lineCol)); layer0.lines.Add(new SceneMeshLine(p2, p3, lineCol)); layer0.lines.Add(new SceneMeshLine(p3, p0, lineCol)); layer0.lines.Add(new SceneMeshLine(p0 + openingUp, p1 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p1 + openingUp, p2 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p2 + openingUp, p3 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p3 + openingUp, p0 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p0, p0 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p1, p1 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p2, p2 + openingUp, lineCol)); layer0.lines.Add(new SceneMeshLine(p3, p3 + openingUp, lineCol)); layer0.labels.Add(new SceneMeshLabel(openingPosition + openingUp, string.Format("Opening {0}", o + 1))); if (volume == BuildingEditor.volume && BuildingEditor.floorplan != null) { Vector3 floorUpA = Vector3.up * volume.CalculateFloorHeight(volume.Floor(BuildingEditor.floorplan)); Vector3 floorUpB = floorUpA + Vector3.up * volume.floorHeight; Color col = isSelectedOpening ? Color.green : Color.red; SceneMeshLayer useLayer = isSelectedOpening ? layer2 : layer2; useLayer.lines.Add(new SceneMeshLine(p0 + floorUpA, p1 + floorUpA, col)); useLayer.lines.Add(new SceneMeshLine(p1 + floorUpA, p2 + floorUpA, col)); useLayer.lines.Add(new SceneMeshLine(p2 + floorUpA, p3 + floorUpA, col)); useLayer.lines.Add(new SceneMeshLine(p3 + floorUpA, p0 + floorUpA, col)); useLayer.lines.Add(new SceneMeshLine(p0 + floorUpB, p1 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p1 + floorUpB, p2 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p2 + floorUpB, p3 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p3 + floorUpB, p0 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p0 + floorUpA, p0 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p1 + floorUpA, p1 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p2 + floorUpA, p2 + floorUpB, col)); useLayer.lines.Add(new SceneMeshLine(p3 + floorUpA, p3 + floorUpB, col)); } } } } } }
public static bool Generate(BuildRMesh mesh, BuildRCollider collider, Vector2[] points, int[] facadeIndices, float roofBaseHeight, IVolume volume) { if (points.Length == 0) { return(false); } if (BuildrUtils.SelfIntersectingPoly(points)) { return(false); } Roof design = volume.roof; float floorWidth = design.floorDepth; float roofDepth = design.depth; float roofHeight = design.height; Surface mainSurface = design.mainSurface; Surface floorSurface = design.floorSurface; int mainSubmesh = mesh.submeshLibrary.SubmeshAdd(mainSurface); int floorSubmesh = mesh.submeshLibrary.SubmeshAdd(floorSurface); //mansard floor if (floorWidth > 0) { OffsetSkeleton offsetFloorPoly = new OffsetSkeleton(points, null, floorWidth); offsetFloorPoly.direction = 1; offsetFloorPoly.Execute(); Shape floorShape = offsetFloorPoly.shape; if (floorShape != null) { ToMesh(ref mesh, ref floorShape, roofBaseHeight, 0, facadeIndices, volume, floorSubmesh, design.floorSurface); points = new Vector2[floorShape.terminatedNodeCount]; for (int i = 0; i < floorShape.terminatedNodeCount; i++) { points[i] = floorShape.TerminatedNode(i).position; } } else { return(false); //todo } } if (points.Length == 0) { return(false); } //mansard pitch OffsetSkeleton offsetRoofPoly = new OffsetSkeleton(points, null, roofDepth); offsetRoofPoly.direction = 1; offsetRoofPoly.Execute(); Shape roofShape = offsetRoofPoly.shape; if (roofShape == null) { return(false); } if (facadeIndices.Length < roofShape.baseEdges.Count) { return(false); } ToMesh(ref mesh, ref roofShape, roofBaseHeight, roofHeight, facadeIndices, volume, mainSubmesh, mainSurface, design.hasDormers); points = new Vector2[roofShape.terminatedNodeCount]; for (int i = 0; i < roofShape.terminatedNodeCount; i++) { points[i] = roofShape.TerminatedNode(i).position; } //mansard top ToMesh(ref mesh, points, roofBaseHeight + roofHeight, facadeIndices, volume, floorSubmesh, floorSurface); return(true); }