public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data) { switch (_data.generateCollider) { case BuildrData.ColliderGenerationModes.None: return; // break; case BuildrData.ColliderGenerationModes.Simple: BuildSimple(_mesh, _data); break; case BuildrData.ColliderGenerationModes.Complex: BuildrBuilding.Build(_mesh, _data); BuildrRoof.Build(_mesh, _data); int numberOfVolumes = _data.plan.numberOfVolumes; for (int v = 0; v < numberOfVolumes; v++) { BuildrInteriors.Build(_mesh, _data, v); BuildrStairs.Build(_mesh, _data, v, BuildrStairs.StairModes.Flat, false); } _mesh.CollapseSubmeshes(); break; } }
public static void Build(DynamicMeshGenericMultiMaterialMesh _mesh, BuildrData _data) { switch(_data.generateCollider) { case BuildrData.ColliderGenerationModes.None: return; // break; case BuildrData.ColliderGenerationModes.Simple: BuildSimple(_mesh,_data); break; case BuildrData.ColliderGenerationModes.Complex: BuildrBuilding.Build(_mesh,_data); BuildrRoof.Build(_mesh, _data); int numberOfVolumes = _data.plan.numberOfVolumes; for(int v = 0; v < numberOfVolumes; v++) { BuildrInteriors.Build(_mesh,_data,v); BuildrStairs.Build(_mesh,_data,v,BuildrStairs.StairModes.Flat,false); } _mesh.CollapseSubmeshes(); break; } }
private static void ExportLowLOD(BuildrData data) { DynamicMeshGenericMultiMaterialMesh dynLODMesh = new DynamicMeshGenericMultiMaterialMesh(); dynLODMesh.subMeshCount = data.textures.Count; BuildrBuildingLowDetail2.Build(dynLODMesh, data); dynLODMesh.CollapseSubmeshes(); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.80f); dynLODMesh.Build(data.includeTangents); Mesh LODMesh = dynLODMesh[0].mesh;//TODO: support many meshes MeshUtility.Optimize(LODMesh); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.90f); string textureName = data.exportFilename + ATLASED_SUFFIX + LOD_SUFFIX; string textureFileName = textureName + ".png"; string newDirectory = ROOT_FOLDER + data.exportFilename; File.WriteAllBytes(newDirectory + "/" + textureFileName, data.LODTextureAtlas.EncodeToPNG()); ExportMaterial[] exportTextures = new ExportMaterial[1]; ExportMaterial newTexture = new ExportMaterial(); newTexture.name = textureName; newTexture.filepath = textureFileName; newTexture.generated = true; exportTextures[0] = newTexture; string LODFileName = data.exportFilename + LOD_SUFFIX; string LODFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(LODFileName, LODFolder, data, LODMesh, exportTextures); if (data.placeIntoScene) { AssetDatabase.Refresh();//ensure the database is up to date... string filePath = LODFolder + LODFileName + FILE_EXTENTION; GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); newModel.transform.position = CURRENT_TRANSFORM.position; newModel.transform.rotation = CURRENT_TRANSFORM.rotation; } Texture2D.DestroyImmediate(data.textureAtlas); Texture2D.DestroyImmediate(data.LODTextureAtlas); }
/// <summary> /// Generate the detail meshes and return the export object /// </summary> /// <param name="mesh"></param> /// <param name="data"></param> /// <returns></returns> public static BuildrDetailExportObject Build(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data) { BuildrDetailExportObject exportObject = new BuildrDetailExportObject(); List<Texture2D> detailTextures = new List<Texture2D>(); List<int> detailSubmeshesWithTextures = new List<int>(); int numberOfDetails = data.details.Count; mesh.Clear(); mesh.subMeshCount = numberOfDetails; for(int d = 0; d < numberOfDetails; d++) { BuildrDetail detail = data.details[d]; if(detail.mesh == null) continue; int faceIndex = detail.face; Vector3 position = Vector3.zero; BuildrPlan plan = data.plan; int numberOfVolumes = plan.numberOfVolumes; Vector2 faceUv = detail.faceUv; Quaternion faceAngle = Quaternion.identity; //Place the detail mesh if (detail.type == BuildrDetail.Types.Facade) { //find facade int facadeCount = 0; bool facadeFound = false; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; int numberOfVolumePoints = volume.points.Count; for (int p = 0; p < numberOfVolumePoints; p++) { if (facadeCount == faceIndex) { int indexA = p; int indexB = (p + 1) % numberOfVolumePoints; Vector3 p0 = plan.points[volume.points[indexA]].vector3; Vector3 p1 = plan.points[volume.points[indexB]].vector3; Vector3 basePosition = Vector3.Lerp(p0, p1, faceUv.x); Vector3 detailHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight * faceUv.y); Vector3 facadeCross = Vector3.Cross(Vector3.up, p1 - p0).normalized; Vector3 detailDepth = facadeCross * detail.faceHeight; faceAngle = Quaternion.LookRotation(facadeCross); position = basePosition + detailHeight + detailDepth; facadeFound = true; break; } facadeCount++; } if (facadeFound) break; } } else//roof detail { BuildrVolume volume = plan.volumes[Mathf.Clamp(0,numberOfVolumes-1,faceIndex)]; int numberOfVolumePoints = volume.points.Count; Vector3 minimumRoofPoint = plan.points[volume.points[0]].vector3; Vector3 maximumRoofPoint = minimumRoofPoint; for (int p = 1; p < numberOfVolumePoints; p++) { Vector3 p0 = plan.points[volume.points[p]].vector3; if (p0.x < minimumRoofPoint.x) minimumRoofPoint.x = p0.x; if (p0.z < minimumRoofPoint.y) minimumRoofPoint.y = p0.z; if (p0.x > maximumRoofPoint.x) maximumRoofPoint.x = p0.x; if (p0.z > maximumRoofPoint.y) maximumRoofPoint.y = p0.z; } position.x = Mathf.Lerp(minimumRoofPoint.x, maximumRoofPoint.x, faceUv.x); position.z = Mathf.Lerp(minimumRoofPoint.y, maximumRoofPoint.y, faceUv.y); position.y = volume.numberOfFloors * data.floorHeight + detail.faceHeight; } Quaternion userRotation = Quaternion.Euler(detail.userRotation); int vertexCount = detail.mesh.vertexCount; Vector3[] verts = new Vector3[vertexCount]; Quaternion rotate = faceAngle * userRotation; for (int i = 0; i < vertexCount; i++) { Vector3 sourceVertex = Vector3.Scale(detail.mesh.vertices[i], detail.scale); Vector3 outputVertex = (rotate) * sourceVertex + position; verts[i] = outputVertex; } mesh.AddData(verts, detail.mesh.uv, detail.mesh.triangles, d); detail.worldPosition = position; detail.worldRotation = rotate; if (detail.material.mainTexture != null) { #if UNITY_EDITOR string texturePath = AssetDatabase.GetAssetPath(detail.material.mainTexture); TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (!textureImporter.isReadable) { Debug.LogWarning("The texture you have selected is not readable. Cannot render"); return exportObject; } detailTextures.Add((Texture2D)detail.material.mainTexture); detailSubmeshesWithTextures.Add(d); #endif } } if(detailtexture!=null) Object.DestroyImmediate(detailtexture); List<Mesh> outputMeshes = new List<Mesh>(); if (detailSubmeshesWithTextures.Count > 0) { Rect[] textureRects = BuildrTexturePacker2.Pack(out detailtexture, detailTextures.ToArray(), 512); if(detailSubmeshesWithTextures.Count > 0) mesh.Atlas(detailSubmeshesWithTextures.ToArray(), textureRects); mesh.CollapseSubmeshes(); mesh.Build(); int numberOfMeshes = mesh.meshCount; for (int i = 0; i < numberOfMeshes; i++) outputMeshes.Add(mesh[i].mesh); } exportObject.detailMeshes = outputMeshes.ToArray(); exportObject.texture = detailtexture; return exportObject; /*if (detailMat == null) detailMat = new Material(Shader.Find("Diffuse")); detailMat.mainTexture = detailtexture; List<Mesh> outputMeshes = new List<Mesh>(); for (int i = 0; i < numberOfMeshes; i++) { outputMeshes.Add(mesh[i].mesh); GameObject details = new GameObject("details " + i); details.AddComponent<MeshFilter>().mesh = mesh[i].mesh; details.AddComponent<MeshRenderer>().sharedMaterial = detailMat; detailGameobjects.Add(details); } } // Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec"); return detailGameobjects.ToArray();*/ }
private static void ExportLowLOD(BuildrData data) { DynamicMeshGenericMultiMaterialMesh dynLODMesh = new DynamicMeshGenericMultiMaterialMesh(); dynLODMesh.subMeshCount = data.textures.Count; BuildrBuildingLowDetail2.Build(dynLODMesh, data); dynLODMesh.CollapseSubmeshes(); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.80f); dynLODMesh.Build(data.includeTangents); Mesh LODMesh = dynLODMesh[0].mesh;//TODO: support many meshes MeshUtility.Optimize(LODMesh); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.90f); string textureName = data.exportFilename + ATLASED_SUFFIX + LOD_SUFFIX; string textureFileName = textureName + ".png"; string newDirectory = ROOT_FOLDER + data.exportFilename; File.WriteAllBytes(newDirectory + "/" + textureFileName, data.LODTextureAtlas.EncodeToPNG()); ExportMaterial[] exportTextures = new ExportMaterial[1]; ExportMaterial newTexture = new ExportMaterial(); newTexture.name = textureName; newTexture.filepath = textureFileName; newTexture.generated = true; exportTextures[0] = newTexture; string LODFileName = data.exportFilename + LOD_SUFFIX; string LODFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(LODFileName, LODFolder, data, LODMesh, exportTextures); if (data.placeIntoScene) { AssetDatabase.Refresh();//ensure the database is up to date... string filePath = LODFolder + LODFileName + FILE_EXTENTION; GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); newModel.transform.position = CURRENT_TRANSFORM.position; newModel.transform.rotation = CURRENT_TRANSFORM.rotation; } Texture2D.DestroyImmediate(data.textureAtlas); Texture2D.DestroyImmediate(data.LODTextureAtlas); }
public void UpdateRender(renderModes _mode) { if (data.plan == null) { return; } if (data.floorHeight == 0) { return; } if (fullMesh == null) { fullMesh = new DynamicMeshGenericMultiMaterialMesh(); } fullMesh.Clear(); fullMesh.subMeshCount = data.textures.Count; foreach (DynamicMeshGenericMultiMaterialMesh intMesh in interiorMeshes) { intMesh.Clear(); } switch (_mode) { case renderModes.full: BuildrBuilding.Build(fullMesh, data); BuildrRoof.Build(fullMesh, data); break; case renderModes.lowDetail: BuildrBuildingLowDetail2.Build(fullMesh, data); fullMesh.CollapseSubmeshes(); break; case renderModes.box: BuildrBuildingBox.Build(fullMesh, data); break; } fullMesh.Build(false); while (meshHolders.Count > 0) { GameObject destroyOld = meshHolders[0]; meshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } int numberOfMeshes = fullMesh.meshCount; for (int i = 0; i < numberOfMeshes; i++) { GameObject newMeshHolder = new GameObject("model " + (i + 1)); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = Vector3.zero; meshFilt = newMeshHolder.AddComponent <MeshFilter>(); meshRend = newMeshHolder.AddComponent <MeshRenderer>(); meshFilt.mesh = fullMesh[i].mesh; meshHolders.Add(newMeshHolder); } while (interiorMeshHolders.Count > 0) { GameObject destroyOld = interiorMeshHolders[0]; interiorMeshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } switch (_mode) { case renderModes.full: UpdateInteriors(); UpdateTextures(); break; case renderModes.lowDetail: meshRend.sharedMaterials = new Material[0]; lowDetailMat.mainTexture = data.LODTextureAtlas; meshRend.sharedMaterial = lowDetailMat; break; case renderModes.box: meshRend.sharedMaterials = new Material[0]; lowDetailMat.mainTexture = data.textures[0].texture; meshRend.sharedMaterial = lowDetailMat; break; } }
/// <summary> /// Generate the detail meshes and return the export object /// </summary> /// <param name="mesh"></param> /// <param name="data"></param> /// <returns></returns> public static BuildrDetailExportObject Build(DynamicMeshGenericMultiMaterialMesh mesh, BuildrData data) { BuildrDetailExportObject exportObject = new BuildrDetailExportObject(); List <Texture2D> detailTextures = new List <Texture2D>(); List <int> detailSubmeshesWithTextures = new List <int>(); int numberOfDetails = data.details.Count; mesh.Clear(); mesh.subMeshCount = numberOfDetails; for (int d = 0; d < numberOfDetails; d++) { BuildrDetail detail = data.details[d]; if (detail.mesh == null) { continue; } int faceIndex = detail.face; Vector3 position = Vector3.zero; BuildrPlan plan = data.plan; int numberOfVolumes = plan.numberOfVolumes; Vector2 faceUv = detail.faceUv; Quaternion faceAngle = Quaternion.identity; //Place the detail mesh if (detail.type == BuildrDetail.Types.Facade) { //find facade int facadeCount = 0; bool facadeFound = false; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; int numberOfVolumePoints = volume.points.Count; for (int p = 0; p < numberOfVolumePoints; p++) { if (facadeCount == faceIndex) { int indexA = p; int indexB = (p + 1) % numberOfVolumePoints; Vector3 p0 = plan.points[volume.points[indexA]].vector3; Vector3 p1 = plan.points[volume.points[indexB]].vector3; Vector3 basePosition = Vector3.Lerp(p0, p1, faceUv.x); Vector3 detailHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight * faceUv.y); Vector3 facadeCross = Vector3.Cross(Vector3.up, p1 - p0).normalized; Vector3 detailDepth = facadeCross * detail.faceHeight; faceAngle = Quaternion.LookRotation(facadeCross); position = basePosition + detailHeight + detailDepth; facadeFound = true; break; } facadeCount++; } if (facadeFound) { break; } } } else//roof detail { BuildrVolume volume = plan.volumes[Mathf.Clamp(0, numberOfVolumes - 1, faceIndex)]; int numberOfVolumePoints = volume.points.Count; Vector3 minimumRoofPoint = plan.points[volume.points[0]].vector3; Vector3 maximumRoofPoint = minimumRoofPoint; for (int p = 1; p < numberOfVolumePoints; p++) { Vector3 p0 = plan.points[volume.points[p]].vector3; if (p0.x < minimumRoofPoint.x) { minimumRoofPoint.x = p0.x; } if (p0.z < minimumRoofPoint.y) { minimumRoofPoint.y = p0.z; } if (p0.x > maximumRoofPoint.x) { maximumRoofPoint.x = p0.x; } if (p0.z > maximumRoofPoint.y) { maximumRoofPoint.y = p0.z; } } position.x = Mathf.Lerp(minimumRoofPoint.x, maximumRoofPoint.x, faceUv.x); position.z = Mathf.Lerp(minimumRoofPoint.y, maximumRoofPoint.y, faceUv.y); position.y = volume.numberOfFloors * data.floorHeight + detail.faceHeight; } Quaternion userRotation = Quaternion.Euler(detail.userRotation); int vertexCount = detail.mesh.vertexCount; Vector3[] verts = new Vector3[vertexCount]; Quaternion rotate = faceAngle * userRotation; for (int i = 0; i < vertexCount; i++) { Vector3 sourceVertex = Vector3.Scale(detail.mesh.vertices[i], detail.scale); Vector3 outputVertex = (rotate) * sourceVertex + position; verts[i] = outputVertex; } mesh.AddData(verts, detail.mesh.uv, detail.mesh.triangles, d); detail.worldPosition = position; detail.worldRotation = rotate; if (detail.material.mainTexture != null) { #if UNITY_EDITOR string texturePath = AssetDatabase.GetAssetPath(detail.material.mainTexture); TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (!textureImporter.isReadable) { Debug.LogWarning("The texture you have selected is not readable. Cannot render"); return(exportObject); } detailTextures.Add((Texture2D)detail.material.mainTexture); detailSubmeshesWithTextures.Add(d); #endif } } if (detailtexture != null) { Object.DestroyImmediate(detailtexture); } List <Mesh> outputMeshes = new List <Mesh>(); if (detailSubmeshesWithTextures.Count > 0) { Rect[] textureRects = BuildrTexturePacker2.Pack(out detailtexture, detailTextures.ToArray(), 512); if (detailSubmeshesWithTextures.Count > 0) { mesh.Atlas(detailSubmeshesWithTextures.ToArray(), textureRects); } mesh.CollapseSubmeshes(); mesh.Build(); int numberOfMeshes = mesh.meshCount; for (int i = 0; i < numberOfMeshes; i++) { outputMeshes.Add(mesh[i].mesh); } } exportObject.detailMeshes = outputMeshes.ToArray(); exportObject.texture = detailtexture; return(exportObject); /*if (detailMat == null) * detailMat = new Material(Shader.Find("Diffuse")); * detailMat.mainTexture = detailtexture; * List<Mesh> outputMeshes = new List<Mesh>(); * for (int i = 0; i < numberOfMeshes; i++) * { * outputMeshes.Add(mesh[i].mesh); * GameObject details = new GameObject("details " + i); * details.AddComponent<MeshFilter>().mesh = mesh[i].mesh; * details.AddComponent<MeshRenderer>().sharedMaterial = detailMat; * detailGameobjects.Add(details); * } * } * // Debug.Log("BuildR Detail Pack Complete: " + (Time.realtimeSinceStartup - timestart) + " sec"); * return detailGameobjects.ToArray();*/ }