private static void ExportCollider(BuildrData data) { DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh(); COL_MESH.subMeshCount = data.textures.Count; BuildrBuildingCollider.Build(COL_MESH, data); // COL_MESH.CollapseSubmeshes(); COL_MESH.Build(false); ExportMaterial[] exportTextures = new ExportMaterial[1]; ExportMaterial newTexture = new ExportMaterial(); newTexture.name = "blank"; newTexture.filepath = ""; newTexture.generated = true; exportTextures[0] = newTexture; int numberOfColliderMeshes = COL_MESH.meshCount; for (int i = 0; i < numberOfColliderMeshes; i++) { MeshUtility.Optimize(COL_MESH[i].mesh); string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : ""); string ColliderFileName = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex; string ColliderFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures); } }
public void UpdateCollider() { if (data.generateCollider != BuildrData.ColliderGenerationModes.None) { if (data.floorHeight == 0) { return; } if (colliderMesh == null) { colliderMesh = new DynamicMeshGenericMultiMaterialMesh(); } colliderMesh.Clear(); colliderMesh.subMeshCount = 1; BuildrBuildingCollider.Build(colliderMesh, data); colliderMesh.Build(false); int numberOfStairMeshes = colliderMesh.meshCount; for (int i = 0; i < numberOfStairMeshes; i++) { string meshName = "collider"; if (numberOfStairMeshes > 1) { meshName += " mesh " + (i + 1); } GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; meshFilt = newMeshHolder.AddComponent <MeshFilter>(); meshRend = newMeshHolder.AddComponent <MeshRenderer>(); meshFilt.mesh = colliderMesh[i].mesh; colliderHolders.Add(newMeshHolder); } } }
private static int[] ExportStairwells(BuildrData data) { int numberOfVolumes = data.plan.numberOfVolumes; int[] returnNumberOfMeshes = new int[numberOfVolumes]; for (int v = 0; v < numberOfVolumes; v++) { BuildrVolume volume = data.plan.volumes[v]; int numberOfUnpackedTextures = data.textures.Count; List <ExportMaterial> exportTextures = new List <ExportMaterial>(); if (!volume.generateStairs) { continue; } DynamicMeshGenericMultiMaterialMesh INT_STAIRWELL = new DynamicMeshGenericMultiMaterialMesh(); INT_STAIRWELL.subMeshCount = data.textures.Count; BuildrStairs.Build(INT_STAIRWELL, data, v, BuildrStairs.StairModes.Stepped, true); INT_STAIRWELL.Build(data.includeTangents); List <int> unusedStairTextures = INT_STAIRWELL.unusedSubmeshes; numberOfUnpackedTextures = data.textures.Count; for (int t = 0; t < numberOfUnpackedTextures; t++) { if (unusedStairTextures.Contains(t)) { continue;//skip, unused } ExportMaterial newTexture = new ExportMaterial(); newTexture.name = data.textures[t].name; newTexture.material = data.textures[t].material; newTexture.generated = false; newTexture.filepath = data.textures[t].filePath; exportTextures.Add(newTexture); } int numberOfStairMeshes = INT_STAIRWELL.meshCount; for (int i = 0; i < numberOfStairMeshes; i++) { MeshUtility.Optimize(INT_STAIRWELL[i].mesh); string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numberOfStairMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(DetailFileName, DetailFolder, data, INT_STAIRWELL[i].mesh, exportTextures.ToArray()); } returnNumberOfMeshes[v] = numberOfStairMeshes; } return(returnNumberOfMeshes); }
public void UpdateInteriors() { while (interiorMeshHolders.Count > 0) { GameObject destroyOld = interiorMeshHolders[0]; interiorMeshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } interiorMeshes.Clear(); if (data.renderInteriors) { int numberOfVolumes = data.plan.numberOfVolumes; for (int v = 0; v < numberOfVolumes; v++) { DynamicMeshGenericMultiMaterialMesh interiorMesh = new DynamicMeshGenericMultiMaterialMesh(); interiorMesh.subMeshCount = data.textures.Count; BuildrInteriors.Build(interiorMesh, data, v); interiorMesh.Build(false); int numberOfInteriorMeshes = interiorMesh.meshCount; for (int i = 0; i < numberOfInteriorMeshes; i++) { string meshName = "model interior"; if (numberOfVolumes > 0) { meshName += " volume " + (v + 1); } if (numberOfInteriorMeshes > 1) { meshName += " mesh " + (i + 1); } GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = Vector3.zero; meshFilt = newMeshHolder.AddComponent <MeshFilter>(); meshRend = newMeshHolder.AddComponent <MeshRenderer>(); meshFilt.mesh = interiorMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); } } } }
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); }
private static void ExportCollider(TrackBuildR data) { DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh(); // COL_MESH.subMeshCount = data.textures.Count; // BuildrBuildingCollider.Build(COL_MESH, data); // COL_MESH.CollapseSubmeshes(); COL_MESH.Build(false); ExportMaterial[] exportTextures = new ExportMaterial[1]; ExportMaterial newTexture = new ExportMaterial(); newTexture.name = "blank"; newTexture.filepath = ""; newTexture.generated = true; exportTextures[0] = newTexture; int numberOfColliderMeshes = COL_MESH.meshCount; for (int i = 0; i < numberOfColliderMeshes; i++) { MeshUtility.Optimize(COL_MESH[i].mesh); string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : ""); string ColliderFileName = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex; string ColliderFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures); } //string newDirectory = rootFolder+track.exportFilename; //if(!CreateFolder(newDirectory)) // return; // ExportMaterial[] exportTextures = new ExportMaterial[1]; // ExportMaterial newTexture = new ExportMaterial(); // newTexture.customName = ""; // newTexture.filepath = ""; // newTexture.generated = true; // exportTextures[0] = newTexture; // Export(track.exportFilename + COLLIDER_SUFFIX, ROOT_FOLDER + track.exportFilename + "/", track, EXPORT_MESH, exportTextures); // // COL_MESH = null; // EXPORT_MESH = null; }
private static void ExportModel(BuildrData data) { try { EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f); //check overwrites... string newDirectory = ROOT_FOLDER + data.exportFilename; if(!CreateFolder(newDirectory)) { EditorUtility.ClearProgressBar(); return; } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.05f); if(data.fullmesh) { //export unpacked model DYN_MESH = new DynamicMeshGenericMultiMaterialMesh(); DYN_MESH.subMeshCount = data.textures.Count; BuildrBuilding.Build(DYN_MESH, data); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.30f); BuildrRoof.Build(DYN_MESH, data); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.60f); DYN_MESH.Build(data.includeTangents); int meshCount = DYN_MESH.meshCount; List<int> unusedTextures = DYN_MESH.unusedSubmeshes; int numberOfUnpackedTextures = data.textures.Count; List<ExportMaterial> exportTextureList = new List<ExportMaterial>(); for (int t = 0; t < numberOfUnpackedTextures; t++) { if (unusedTextures.Contains(t)) continue;//skip, unused ExportMaterial newTexture = new ExportMaterial(); newTexture.name = data.textures[t].name; newTexture.material = data.textures[t].material; newTexture.generated = false; newTexture.filepath = data.textures[t].filePath; exportTextureList.Add(newTexture); } for(int i = 0; i < meshCount; i++) { EXPORT_MESH = DYN_MESH[i].mesh; MeshUtility.Optimize(EXPORT_MESH); Export(data, EXPORT_MESH, exportTextureList.ToArray()); string filenameSuffix = (meshCount>1)? i.ToString() : ""; string filename = data.exportFilename + filenameSuffix; Export(filename, ROOT_FOLDER + data.exportFilename + "/", data, EXPORT_MESH, exportTextureList.ToArray()); } } //Export Collider if(data.generateCollider != BuildrData.ColliderGenerationModes.None) ExportCollider(data); int[] numberOfInteriorMeshes = new int[data.plan.numberOfVolumes]; if(data.renderInteriors && data.fullmesh) numberOfInteriorMeshes = ExportInteriors(data); int[] numberOfStairwells = new int[data.plan.numberOfVolumes]; if (data.renderInteriors && data.fullmesh) numberOfStairwells = ExportStairwells(data); int numberOfDetailMeshes = 0; if(data.fullmesh) numberOfDetailMeshes = ExportDetails(data); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f); //Place exported version into scene if(data.fullmesh) { AssetDatabase.Refresh();//ensure the database is up to date... GameObject baseObject = new GameObject(data.exportFilename); if((data.createPrefabOnExport || data.placeIntoScene)) { baseObject.transform.position = CURRENT_TRANSFORM.position; baseObject.transform.rotation = CURRENT_TRANSFORM.rotation; string modelFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + FILE_EXTENTION; GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath)); newModel.name = "model"; newModel.transform.parent = baseObject.transform; newModel.transform.localPosition = Vector3.zero; newModel.transform.localRotation = Quaternion.identity; if(data.generateCollider != BuildrData.ColliderGenerationModes.None) { GameObject colliderObject = new GameObject("collider"); string colliderFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + COLLIDER_SUFFIX + FILE_EXTENTION; colliderObject.AddComponent<MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(colliderFilePath, typeof(Mesh)); colliderObject.transform.parent = baseObject.transform; colliderObject.transform.localPosition = Vector3.zero; colliderObject.transform.localRotation = Quaternion.identity; } for (int i = 0; i < numberOfDetailMeshes; i++) { string detailSuffixIndex = ((numberOfDetailMeshes > 1) ? "_" + i : ""); string detailFileName = data.exportFilename + DETAIL_SUFFIX + detailSuffixIndex; string detailFolder = ROOT_FOLDER + data.exportFilename + "/"; string detailFilepath = detailFolder + detailFileName + FILE_EXTENTION; GameObject detailObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(detailFilepath)); detailObject.name = "details"; detailObject.transform.parent = baseObject.transform; detailObject.transform.localPosition = Vector3.zero; detailObject.transform.localRotation = Quaternion.identity; } int numberOfVolumes = data.plan.numberOfVolumes; GameObject interiorHolder = new GameObject("interiors"); interiorHolder.transform.parent = baseObject.transform; interiorHolder.transform.localPosition = Vector3.zero; interiorHolder.transform.localRotation = Quaternion.identity; for (int v = 0; v < numberOfInteriorMeshes.Length; v++) { int numMeshes = numberOfInteriorMeshes[v]; for (int i = 0; i < numMeshes; i++) { string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; string filePath = DetailFolder + DetailFileName + FILE_EXTENTION; GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); interiorObject.name = INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex; interiorObject.transform.parent = interiorHolder.transform; interiorObject.transform.localPosition = Vector3.zero; interiorObject.transform.localRotation = Quaternion.identity; } } for(int v = 0; v < numberOfStairwells.Length; v++) { int numMeshes = numberOfStairwells[v]; for (int i = 0; i < numMeshes; i++) { string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; string filePath = DetailFolder + DetailFileName + FILE_EXTENTION; GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); interiorObject.name = STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; interiorObject.transform.parent = interiorHolder.transform; interiorObject.transform.localPosition = data.plan.volumes[v].stairBaseVector[i]; interiorObject.transform.localRotation = Quaternion.identity; } } } if(data.createPrefabOnExport) { string prefabPath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + ".prefab"; Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if(prefab == null) prefab = PrefabUtility.CreateEmptyPrefab(prefabPath); PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab); } if(!data.placeIntoScene) Object.DestroyImmediate(baseObject); } if(data.exportLowLOD) { ExportLowLOD(data); } DYN_MESH = null; EXPORT_MESH = null; EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssets(); AssetDatabase.Refresh(); }catch(System.Exception e) { Debug.LogError("BuildR Export Error: "+e); EditorUtility.ClearProgressBar(); } }
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); }
private static void ExportCollider(BuildrData data) { DynamicMeshGenericMultiMaterialMesh COL_MESH = new DynamicMeshGenericMultiMaterialMesh(); COL_MESH.subMeshCount = data.textures.Count; BuildrBuildingCollider.Build(COL_MESH, data); // COL_MESH.CollapseSubmeshes(); COL_MESH.Build(false); ExportMaterial[] exportTextures = new ExportMaterial[1]; ExportMaterial newTexture = new ExportMaterial(); newTexture.name = "blank"; newTexture.filepath = ""; newTexture.generated = true; exportTextures[0] = newTexture; int numberOfColliderMeshes = COL_MESH.meshCount; for (int i = 0; i < numberOfColliderMeshes; i++) { MeshUtility.Optimize(COL_MESH[i].mesh); string ColliderSuffixIndex = ((numberOfColliderMeshes > 1) ? "_" + i : ""); string ColliderFileName = data.exportFilename + COLLIDER_SUFFIX + ColliderSuffixIndex; string ColliderFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(ColliderFileName, ColliderFolder, data, COL_MESH[i].mesh, exportTextures); } }
public void UpdateInteriors() { while (interiorMeshHolders.Count > 0) { GameObject destroyOld = interiorMeshHolders[0]; interiorMeshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } interiorMeshes.Clear(); if (data.renderInteriors) { int numberOfVolumes = data.plan.numberOfVolumes; for (int v = 0; v < numberOfVolumes; v++) { DynamicMeshGenericMultiMaterialMesh interiorMesh = new DynamicMeshGenericMultiMaterialMesh(); interiorMesh.subMeshCount = data.textures.Count; BuildrInteriors.Build(interiorMesh, data, v); interiorMesh.Build(false); int numberOfInteriorMeshes = interiorMesh.meshCount; for (int i = 0; i < numberOfInteriorMeshes; i++) { string meshName = "model interior"; if (numberOfVolumes > 0) meshName += " volume " + (v + 1); if (numberOfInteriorMeshes > 1) meshName += " mesh " + (i + 1); GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = Vector3.zero; meshFilt = newMeshHolder.AddComponent<MeshFilter>(); meshRend = newMeshHolder.AddComponent<MeshRenderer>(); meshFilt.mesh = interiorMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); } } } }
public void UpdateRender() { if (track.numberOfCurves == 0) { return; } track.RecalculateCurves(); float trackMeshRes = track.meshResolution; float bumperDistanceA = 0; float bumperDistanceB = 0; int numberOfCurves = track.numberOfCurves; bool renderTrack = track.render; float UVOffset = 0; int polyCount = 0; for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; DynamicMeshGenericMultiMaterialMesh dynamicTrackMesh = curve.dynamicTrackMesh; DynamicMeshGenericMultiMaterialMesh dynamicBoundaryMesh = curve.dynamicBoundaryMesh; DynamicMeshGenericMultiMaterialMesh dynamicOffroadMesh = curve.dynamicOffroadMesh; DynamicMeshGenericMultiMaterialMesh dynamicBumperMesh = curve.dynamicBumperMesh; DynamicMeshGenericMultiMaterialMesh dynamicColliderMesh = curve.dynamicColliderMesh; DynamicMeshGenericMultiMaterialMesh dynamicBottomMesh = curve.dynamicBottomMesh; if (!curve.render || !renderTrack) { dynamicTrackMesh.Clear(); dynamicBoundaryMesh.Clear(); dynamicColliderMesh.Clear(); dynamicOffroadMesh.Clear(); dynamicBumperMesh.Clear(); dynamicBottomMesh.Clear(); } if (curve.shouldReRender && curve.render && renderTrack) { dynamicTrackMesh.Clear(); dynamicTrackMesh.subMeshCount = 1; dynamicBoundaryMesh.Clear(); dynamicBoundaryMesh.subMeshCount = 1; dynamicColliderMesh.Clear(); dynamicColliderMesh.subMeshCount = 1; dynamicOffroadMesh.Clear(); dynamicOffroadMesh.subMeshCount = 1; dynamicBumperMesh.Clear(); dynamicBumperMesh.subMeshCount = 1; dynamicBottomMesh.Clear(); dynamicBottomMesh.subMeshCount = 1; dynamicTrackMesh.name = "curve " + i + " track mesh"; dynamicBoundaryMesh.name = "curve " + i + " boundary mesh"; dynamicColliderMesh.name = "curve " + i + " trackCollider mesh"; dynamicOffroadMesh.name = "curve " + i + " offroad mesh"; dynamicBumperMesh.name = "curve " + i + " bumper mesh"; dynamicBottomMesh.name = "curve " + i + " bottom mesh"; bool trackTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.trackTextureStyleIndex).flipped : false; bool boundaryTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.boundaryTextureStyleIndex).flipped : false; bool bumperTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.bumperTextureStyleIndex).flipped : false; bool bottomTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.bottomTextureStyleIndex).flipped : false; int storedPointSize = curve.storedPointSize; float curveLength = curve.arcLength; //Store these points so we can use previous values when Bezier clips itself Vector3 leftPointA = curve.sampledLeftBoundaryPoints[0]; Vector3 rightPointA = curve.sampledRightBoundaryPoints[0]; Vector3 leftPointB = curve.sampledLeftBoundaryPoints[0]; Vector3 rightPointB = curve.sampledRightBoundaryPoints[0]; for (int p = 0; p < storedPointSize - 1; p++) { float tA = curve.normalisedT[p]; float tB = curve.normalisedT[p + 1]; int sampleIndexA = p; int sampleIndexB = sampleIndexA + 1; Vector3 pointA = curve.sampledPoints[sampleIndexA]; Vector3 pointB = curve.sampledPoints[sampleIndexB]; float trackWidthA = curve.sampledWidths[sampleIndexA] * 0.5f; float trackWidthB = curve.sampledWidths[sampleIndexB] * 0.5f; float trackCrownA = curve.sampledCrowns[sampleIndexA]; float trackCrownB = curve.sampledCrowns[sampleIndexB]; Vector3 trackUpA = curve.sampledTrackUps[sampleIndexA]; Vector3 trackUpB = curve.sampledTrackUps[sampleIndexB]; Vector3 trackCrossA = curve.sampledTrackCrosses[sampleIndexA]; Vector3 trackCrossB = curve.sampledTrackCrosses[sampleIndexB]; float trackAngle = curve.sampledAngles[sampleIndexA]; if (trackUpA == Vector3.zero || trackUpB == Vector3.zero) { return; } //TrackBuildRTexture texture = track.Texture(curve.trackTextureStyleIndex) ;// track.trackTexture; int pointANumber = Mathf.Max(Mathf.CeilToInt(trackWidthA / trackMeshRes / 2) * 2, 2); //number of verts along line A int pointBNumber = Mathf.Max(Mathf.CeilToInt(trackWidthB / trackMeshRes / 2) * 2, 2); //number of verts along line B int numberOfNewVerts = pointANumber + pointBNumber; Vector3[] uncrownedVerts = new Vector3[numberOfNewVerts]; if (curve.clipArrayLeft[sampleIndexA]) { leftPointA = (pointA + (trackCrossA * -trackWidthA)); } if (curve.clipArrayRight[sampleIndexA]) { rightPointA = (pointA + (trackCrossA * trackWidthA)); } float curveLengthA = (curveLength * tA) / trackWidthA + UVOffset; float curveLengthB = (curveLength * tB) / trackWidthB + UVOffset; float lerpASize = 1.0f / (pointANumber - 1); //track vertex/uv data for point nextNormIndex Vector3[] newAPoints = new Vector3[pointANumber]; Vector3[] newTrackPoints = new Vector3[pointANumber + pointBNumber]; Vector2[] newTrackUVs = new Vector2[pointANumber + pointBNumber]; for (int pa = 0; pa < pointANumber; pa++) { float lerpValue = lerpASize * pa; Vector3 crownVector = Quaternion.LookRotation(trackUpA) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownA); Vector3 uncrownedVert = Vector3.Lerp(leftPointA, rightPointA, lerpValue); uncrownedVerts[pa] = uncrownedVert; Vector3 newVert = uncrownedVert + crownVector; newAPoints[pa] = newVert; newTrackPoints[pa] = newVert; Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthA) : new Vector2(curveLengthA, lerpValue); newTrackUVs[pa] = newUV; } //track vertex/uv data for point prevNormIndex if (curve.clipArrayLeft[sampleIndexB]) { leftPointB = (pointB + (trackCrossB * -trackWidthB)); } if (curve.clipArrayRight[sampleIndexB]) { rightPointB = (pointB + (trackCrossB * trackWidthB)); } float lerpBSize = 1.0f / (pointBNumber - 1); Vector3[] newBPoints = new Vector3[pointBNumber]; for (int pb = 0; pb < pointBNumber; pb++) { float lerpValue = lerpBSize * pb; Vector3 crownVector = Quaternion.LookRotation(trackUpB) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownB); Vector3 uncrownedVert = Vector3.Lerp(leftPointB, rightPointB, lerpValue); uncrownedVerts[pb + pointANumber] = uncrownedVert; Vector3 newVert = uncrownedVert + crownVector; newBPoints[pb] = newVert; newTrackPoints[pb + pointANumber] = newVert; Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthB) : new Vector2(curveLengthB, lerpValue); newTrackUVs[pb + pointANumber] = newUV; } int baseTriPointA = 0; int baseTriPointB = pointANumber; int triPointA = baseTriPointA; int triPointB = baseTriPointB; int newTriPointCountA = 1; int newTriPointCountB = 1; int[] newTrackTris = new int[(numberOfNewVerts - 2) * 3]; for (int v = 0; v < numberOfNewVerts - 2; v++) { int newTriPointA = baseTriPointA + newTriPointCountA; int newTriPointB = baseTriPointB + newTriPointCountB; float newTriPointADist, newTriPointBDist; if (newTriPointA >= baseTriPointA + pointANumber) { newTriPointADist = float.PositiveInfinity; } else { newTriPointADist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointA] - uncrownedVerts[baseTriPointA]); } if (newTriPointB >= baseTriPointB + pointBNumber) { newTriPointBDist = float.PositiveInfinity; } else { newTriPointBDist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointB] - uncrownedVerts[baseTriPointB]); } if (newTriPointADist < newTriPointBDist) { newTrackTris[v * 3] = triPointA; newTrackTris[v * 3 + 1] = triPointB; newTrackTris[v * 3 + 2] = newTriPointA; triPointA = newTriPointA; newTriPointCountA++; } else { newTrackTris[v * 3] = triPointA; newTrackTris[v * 3 + 1] = triPointB; newTrackTris[v * 3 + 2] = newTriPointB; triPointB = newTriPointB; newTriPointCountB++; } } dynamicTrackMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0); dynamicColliderMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0); //Boundary float trackBoundaryWallHeight = curve.boundaryHeight;// track.boundaryHeight; Vector3 leftBoundaryPointA, leftBoundaryPointB, rightBoundaryPointA, rightBoundaryPointB; if (track.disconnectBoundary) { leftBoundaryPointA = curve.sampledLeftBoundaryPoints[sampleIndexA]; leftBoundaryPointB = curve.sampledLeftBoundaryPoints[sampleIndexB]; rightBoundaryPointA = curve.sampledRightBoundaryPoints[sampleIndexA]; rightBoundaryPointB = curve.sampledRightBoundaryPoints[sampleIndexB]; } else { leftBoundaryPointA = leftPointA; leftBoundaryPointB = leftPointB; rightBoundaryPointA = rightPointA; rightBoundaryPointB = rightPointB; } Vector3[] newWallVerts; Vector2[] newWallUVs; int[] newWallTris; //Boundary Render Mesh if (curve.renderBounds) { //LEFT newWallVerts = new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackBoundaryWallHeight, leftBoundaryPointB + trackUpB * trackBoundaryWallHeight }; if (!boundaryTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 1, 0, 2, 1, 2, 3 }; // newWallTris = (boundaryTextureFlip) ? (new[] { 1, 0, 2, 1, 2, 3 }) : (new[] { 0,2,1,2,3,1 }); // newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 1, 0, 2, 1, 2, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 }; dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (track.renderBoundaryWallReverse) { newWallTris = new[] { 0, 1, 2, 2, 1, 3 }; // newWallTris = (boundaryTextureFlip) ? (new[] { 0, 1, 2, 2, 1, 3 }) : (new[] { 0, 2, 1, 2, 3, 1 }); dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } //RIGHT newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackBoundaryWallHeight, rightBoundaryPointB + trackUpB * trackBoundaryWallHeight }); //newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }; if (!boundaryTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 0, 1, 2, 2, 1, 3 }; //newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 0, 1, 2, 2, 1, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 }; dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (track.renderBoundaryWallReverse) { newWallTris = new[] { 1, 0, 2, 1, 2, 3 }; dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } } if (curve.trackCollider) { //COLLIDER walls for on track border float trackColliderWallHeight = track.trackColliderWallHeight; if (curve.colliderSides) { newWallVerts = (new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 0, 1, 2, 2, 1, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } //offroad bits if (track.disconnectBoundary) { Vector2 offroadTextureSize = Vector2.one; if (track.numberOfTextures > 0) { offroadTextureSize = track.Texture(curve.offroadTextureStyleIndex).textureUnitSize;// track.offroadTexture.textureUnitSize; } newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB }); newWallUVs = (new[] { new Vector2(leftPointA.x / offroadTextureSize.x, leftPointA.z / offroadTextureSize.y), new Vector2(leftPointB.x / offroadTextureSize.x, leftPointB.z / offroadTextureSize.y), new Vector2(leftBoundaryPointA.x / offroadTextureSize.x, leftBoundaryPointA.z / offroadTextureSize.y), new Vector2(leftBoundaryPointB.x / offroadTextureSize.x, leftBoundaryPointB.z / offroadTextureSize.y) }); newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB }); newWallUVs = (new[] { new Vector2(rightPointA.x / offroadTextureSize.x, rightPointA.z / offroadTextureSize.y), new Vector2(rightPointB.x / offroadTextureSize.x, rightPointB.z / offroadTextureSize.y), new Vector2(rightBoundaryPointA.x / offroadTextureSize.x, rightBoundaryPointA.z / offroadTextureSize.y), new Vector2(rightBoundaryPointB.x / offroadTextureSize.x, rightBoundaryPointB.z / offroadTextureSize.y) }); newWallTris = (new[] { 0, 1, 2, 2, 1, 3 }); dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 0, 1, 2, 2, 1, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } if (track.includeColliderRoof) { newWallVerts = (new[] { leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } } if ((track.trackBumpers && curve.generateBumpers) || curve.generateBumpers) { float bumperWidth = track.bumperWidth; float bumperHeight = track.bumperHeight; Vector3 bumperRaisedA = trackUpA * bumperHeight; Vector3 bumperRaisedB = trackUpB * bumperHeight; float trackAngleThreashold = track.bumperAngleThresold; //left bumpers if (trackAngle >= trackAngleThreashold) { Vector3 offroadEdgeDirectionA = (leftBoundaryPointA - leftPointA).normalized; Vector3 trackEdgeDirectionA = (newAPoints[1] - newAPoints[0]).normalized; Vector3 bumperDirectionA = (Vector3.Project(offroadEdgeDirectionA, trackUpA) - trackEdgeDirectionA).normalized; Vector3 offroadEdgeDirectionB = (leftBoundaryPointB - leftPointB).normalized; Vector3 trackEdgeDirectionB = (newBPoints[1] - newBPoints[0]).normalized; Vector3 bumperDirectionB = (Vector3.Project(offroadEdgeDirectionB, trackUpB) - trackEdgeDirectionB).normalized; float trackEdgeA = Vector3.Distance(pointA, leftPointA); float offroadEdgeA = Vector3.Distance(pointA, leftBoundaryPointA); bool offroadBumper = (trackEdgeA < (offroadEdgeA - bumperWidth)); Vector3 bumperLeft0 = (offroadBumper ? leftPointA + bumperDirectionA * bumperWidth : leftBoundaryPointA) + bumperRaisedA; Vector3 bumperLeft1 = (offroadBumper ? leftPointA : bumperLeft0 - (bumperDirectionA * bumperWidth) - bumperRaisedB);//bumperLeft0 + (trackEdgeDirectionA * bumperWidth)) - bumperRaisedB; Vector3 bumperLeft2 = (offroadBumper ? leftPointB + bumperDirectionB * bumperWidth : leftBoundaryPointB) + bumperRaisedB; Vector3 bumperLeft3 = (offroadBumper ? leftPointB : bumperLeft2 - (bumperDirectionB * bumperWidth) - bumperRaisedB); float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2); float uvStartA, uvEndA; if (track.numberOfTextures > 0) { uvStartA = bumperDistanceA / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y; uvEndA = (bumperDistanceA + bumperSegmentDistanceA) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y; } else { uvStartA = bumperDistanceA; // track.bumperTexture.textureUnitSize.y; uvEndA = (bumperDistanceA + bumperSegmentDistanceA); // track.bumperTexture.textureUnitSize.y; } newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 }); if (!bumperTextureFlip) { newWallUVs = (new[] { new Vector2(uvStartA, 1), new Vector2(uvStartA, 0), new Vector2(uvEndA, 1), new Vector2(uvEndA, 0) }); } else { newWallUVs = (new[] { new Vector2(1, uvStartA), new Vector2(0, uvStartA), new Vector2(1, uvEndA), new Vector2(0, uvEndA) }); } newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); bumperDistanceA += bumperSegmentDistanceA; newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 }); newWallUVs = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero }); newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } //Right bumpers if (trackAngle < -trackAngleThreashold) { Vector3 trackEdgeDirectionA = (newAPoints[pointANumber - 2] - newAPoints[pointANumber - 1]).normalized; Vector3 trackEdgeDirectionB = (newBPoints[pointBNumber - 2] - newBPoints[pointBNumber - 1]).normalized; Vector3 bumperRight0 = ((Vector3.Distance(pointA, rightPointA) < (Vector3.Distance(pointA, rightBoundaryPointA) - bumperWidth)) ? rightPointA : rightBoundaryPointA) + bumperRaisedA; Vector3 bumperRight1 = bumperRight0 + (trackEdgeDirectionA * bumperWidth); Vector3 bumperRight2 = ((Vector3.Distance(pointB, rightPointB) < (Vector3.Distance(pointB, rightBoundaryPointB) - bumperWidth)) ? rightPointB : rightBoundaryPointB) + bumperRaisedB; Vector3 bumperRight3 = bumperRight2 + (trackEdgeDirectionB * bumperWidth); float bumperSegmentDistanceB = Vector3.Distance(bumperRight0, bumperRight2); //float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2); float uvStartB, uvEndB; if (track.numberOfTextures > 0) { uvStartB = bumperDistanceB / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y; uvEndB = (bumperDistanceB + bumperSegmentDistanceB) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y; } else { uvStartB = bumperDistanceB; uvEndB = (bumperDistanceB + bumperSegmentDistanceB); } newWallVerts = (new[] { bumperRight0, bumperRight1, bumperRight2, bumperRight3 }); if (!bumperTextureFlip) { newWallUVs = (new[] { new Vector2(uvStartB, 1), new Vector2(uvStartB, 0), new Vector2(uvEndB, 1), new Vector2(uvEndB, 0) }); } else { newWallUVs = (new[] { new Vector2(1, uvStartB), new Vector2(0, uvStartB), new Vector2(1, uvEndB), new Vector2(0, uvEndB) }); } // newWallTris = (new[] { 1, 0, 2, 1, 2, 3 }); newWallTris = (new[] { 0, 1, 2, 1, 3, 2 }); dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); bumperDistanceB += bumperSegmentDistanceB; } } //Track Bottom Mesh if (curve.extrudeTrack || curve.extrudeTrackBottom) { float extrusionLength = curve.extrudeLength; Vector3 extrusionA = -trackUpA * extrusionLength; Vector3 extrusionB = -trackUpB * extrusionLength; Vector3 pl0 = leftBoundaryPointA; Vector3 pl1 = leftBoundaryPointB; Vector3 pl2 = leftBoundaryPointA + extrusionA; Vector3 pl3 = leftBoundaryPointB + extrusionB; Vector3 pr0 = rightBoundaryPointA; Vector3 pr1 = rightBoundaryPointB; Vector3 pr2 = rightBoundaryPointA + extrusionA; Vector3 pr3 = rightBoundaryPointB + extrusionB; float bevelLerp = 0.5f - curve.extrudeBevel * 0.3333f; Vector3 bevelOutA = trackCrossA.normalized * (trackWidthA * 0.5f); Vector3 bevelOutB = trackCrossB.normalized * (trackWidthB * 0.5f); Vector3 pl2b = Vector3.Lerp(pl2 - bevelOutA, pr2 + bevelOutA, bevelLerp); Vector3 pl3b = Vector3.Lerp(pl3 - bevelOutB, pr3 + bevelOutB, bevelLerp); Vector3 pr2b = Vector3.Lerp(pr2 + bevelOutA, pl2 - bevelOutA, bevelLerp); Vector3 pr3b = Vector3.Lerp(pr3 + bevelOutB, pl3 - bevelOutB, bevelLerp); if (curve.extrudeTrack) { //LEFT newWallVerts = new[] { pl0, pl1, pl2b, pl3b }; if (!bottomTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 1, 0, 2, 1, 2, 3 }; dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (curve.trackCollider) { dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } //RIGHT newWallVerts = (new[] { pr0, pr1, pr2b, pr3b }); if (!bottomTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 0, 1, 2, 2, 1, 3 }; dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (curve.trackCollider) { dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } if (curve.extrudeCurveEnd) { //Ends if (p == 0) { newWallVerts = (new[] { pl0, pl2b, pr0, pr2b }); if (!bottomTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 1, 0, 2, 1, 2, 3 }; dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (curve.trackCollider) { dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } } if (p == storedPointSize - 2) { newWallVerts = (new[] { pl1, pl3b, pr1, pr3b }); if (!bottomTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 0, 1, 2, 2, 1, 3 }; dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (curve.trackCollider) { dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } } } } if (curve.extrudeTrackBottom) { if (!curve.extrudeTrack) { newWallVerts = new[] { pl0, pl1, pr0, pr1 } } ; else { newWallVerts = new[] { pl2b, pl3b, pr2b, pr3b } }; if (!bottomTextureFlip) { newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), } } ; else { newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), } }; newWallTris = new[] { 1, 0, 2, 1, 2, 3 }; dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); if (curve.trackCollider) { dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0); } } } if (p == storedPointSize - 2) { UVOffset = curveLengthB; } } if (curve.holder != null) { DestroyImmediate(curve.holder); } GameObject newCurveMeshHolder = new GameObject("curve " + (i + 1)); newCurveMeshHolder.transform.parent = transform; newCurveMeshHolder.transform.localPosition = Vector3.zero; curve.holder = newCurveMeshHolder; int numberOfMeshes; if (!dynamicTrackMesh.isEmpty) { dynamicTrackMesh.name = "Curve " + i + " Track Mesh"; dynamicTrackMesh.Build(); numberOfMeshes = dynamicTrackMesh.meshCount; for (int m = 0; m < numberOfMeshes; m++) { GameObject newMeshHolder = new GameObject("model " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicTrackMesh[m].mesh; if (track.numberOfTextures > 0) { newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.trackTextureStyleIndex).GetMaterial();// track.trackTexture.material; } #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe); #endif } } if (!dynamicBoundaryMesh.isEmpty) { dynamicBoundaryMesh.Build(); numberOfMeshes = dynamicBoundaryMesh.meshCount; for (int m = 0; m < numberOfMeshes; m++) { GameObject newMeshHolder = new GameObject("boundary " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBoundaryMesh[m].mesh; if (track.numberOfTextures > 0) { newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.boundaryTextureStyleIndex).GetMaterial();// track.trackTexture.material; } #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe); #endif } } if (track.disconnectBoundary && !dynamicOffroadMesh.isEmpty) { dynamicOffroadMesh.Build(); numberOfMeshes = dynamicOffroadMesh.meshCount; for (int m = 0; m < numberOfMeshes; m++) { GameObject newMeshHolder = new GameObject("offroad " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicOffroadMesh[m].mesh; if (track.numberOfTextures > 0) { newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.offroadTextureStyleIndex).GetMaterial();// track.offroadTexture.material; } #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe); #endif } } if (track.includeCollider && curve.trackCollider && !dynamicColliderMesh.isEmpty) { dynamicColliderMesh.Build(); int numberOfColliderMeshes = dynamicColliderMesh.meshCount; for (int m = 0; m < numberOfColliderMeshes; m++) { GameObject newMeshHolder = new GameObject("trackCollider " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshCollider>().sharedMesh = dynamicColliderMesh[m].mesh; } } if (track.trackBumpers && !dynamicBumperMesh.isEmpty) { dynamicBumperMesh.Build(); numberOfMeshes = dynamicBumperMesh.meshCount; for (int m = 0; m < numberOfMeshes; m++) { GameObject newMeshHolder = new GameObject("bumper " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBumperMesh[m].mesh; if (track.numberOfTextures > 0) { newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bumperTextureStyleIndex).GetMaterial();// track.bumperTexture.material; } #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe); #endif } } if (!dynamicBottomMesh.isEmpty) { dynamicBottomMesh.Build(); numberOfMeshes = dynamicBottomMesh.meshCount; for (int m = 0; m < numberOfMeshes; m++) { GameObject newMeshHolder = new GameObject("bottom " + (m + 1)); newMeshHolder.transform.parent = curve.holder.transform; newMeshHolder.transform.localPosition = Vector3.zero; newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBottomMesh[m].mesh; if (track.numberOfTextures > 0) { newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bottomTextureStyleIndex).GetMaterial();// track.trackTexture.material; } #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe); #endif } } } else { if (curve.holder != null && (!curve.render || !renderTrack)) { DestroyImmediate(curve.holder); } } polyCount += dynamicBottomMesh.triangleCount / 3; polyCount += dynamicBoundaryMesh.triangleCount / 3; polyCount += dynamicBumperMesh.triangleCount / 3; polyCount += dynamicOffroadMesh.triangleCount / 3; polyCount += dynamicTrackMesh.triangleCount / 3; } track.TrackRendered(); track.lastPolycount = polyCount; #if UNITY_EDITOR EditorUtility.UnloadUnusedAssets(); #endif }
private static void ExportModel(BuildrData data) { try { EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f); //check overwrites... string newDirectory = ROOT_FOLDER + data.exportFilename; if (!CreateFolder(newDirectory)) { EditorUtility.ClearProgressBar(); return; } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.05f); if (data.fullmesh) { //export unpacked model DYN_MESH = new DynamicMeshGenericMultiMaterialMesh(); DYN_MESH.subMeshCount = data.textures.Count; BuildrBuilding.Build(DYN_MESH, data); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.30f); BuildrRoof.Build(DYN_MESH, data); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.60f); DYN_MESH.Build(data.includeTangents); int meshCount = DYN_MESH.meshCount; List <int> unusedTextures = DYN_MESH.unusedSubmeshes; int numberOfUnpackedTextures = data.textures.Count; List <ExportMaterial> exportTextureList = new List <ExportMaterial>(); for (int t = 0; t < numberOfUnpackedTextures; t++) { if (unusedTextures.Contains(t)) { continue;//skip, unused } ExportMaterial newTexture = new ExportMaterial(); newTexture.name = data.textures[t].name; newTexture.material = data.textures[t].material; newTexture.generated = false; newTexture.filepath = data.textures[t].filePath; exportTextureList.Add(newTexture); } for (int i = 0; i < meshCount; i++) { EXPORT_MESH = DYN_MESH[i].mesh; MeshUtility.Optimize(EXPORT_MESH); Export(data, EXPORT_MESH, exportTextureList.ToArray()); string filenameSuffix = (meshCount > 1)? i.ToString() : ""; string filename = data.exportFilename + filenameSuffix; Export(filename, ROOT_FOLDER + data.exportFilename + "/", data, EXPORT_MESH, exportTextureList.ToArray()); } } //Export Collider if (data.generateCollider != BuildrData.ColliderGenerationModes.None) { ExportCollider(data); } int[] numberOfInteriorMeshes = new int[data.plan.numberOfVolumes]; if (data.renderInteriors && data.fullmesh) { numberOfInteriorMeshes = ExportInteriors(data); } int[] numberOfStairwells = new int[data.plan.numberOfVolumes]; if (data.renderInteriors && data.fullmesh) { numberOfStairwells = ExportStairwells(data); } int numberOfDetailMeshes = 0; if (data.fullmesh) { numberOfDetailMeshes = ExportDetails(data); } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f); //Place exported version into scene if (data.fullmesh) { AssetDatabase.Refresh();//ensure the database is up to date... GameObject baseObject = new GameObject(data.exportFilename); if ((data.createPrefabOnExport || data.placeIntoScene)) { baseObject.transform.position = CURRENT_TRANSFORM.position; baseObject.transform.rotation = CURRENT_TRANSFORM.rotation; string modelFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + FILE_EXTENTION; GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath)); newModel.name = "model"; newModel.transform.parent = baseObject.transform; newModel.transform.localPosition = Vector3.zero; newModel.transform.localRotation = Quaternion.identity; if (data.generateCollider != BuildrData.ColliderGenerationModes.None) { GameObject colliderObject = new GameObject("collider"); string colliderFilePath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + COLLIDER_SUFFIX + FILE_EXTENTION; colliderObject.AddComponent <MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(colliderFilePath, typeof(Mesh)); colliderObject.transform.parent = baseObject.transform; colliderObject.transform.localPosition = Vector3.zero; colliderObject.transform.localRotation = Quaternion.identity; } for (int i = 0; i < numberOfDetailMeshes; i++) { string detailSuffixIndex = ((numberOfDetailMeshes > 1) ? "_" + i : ""); string detailFileName = data.exportFilename + DETAIL_SUFFIX + detailSuffixIndex; string detailFolder = ROOT_FOLDER + data.exportFilename + "/"; string detailFilepath = detailFolder + detailFileName + FILE_EXTENTION; GameObject detailObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(detailFilepath)); detailObject.name = "details"; detailObject.transform.parent = baseObject.transform; detailObject.transform.localPosition = Vector3.zero; detailObject.transform.localRotation = Quaternion.identity; } int numberOfVolumes = data.plan.numberOfVolumes; GameObject interiorHolder = new GameObject("interiors"); interiorHolder.transform.parent = baseObject.transform; interiorHolder.transform.localPosition = Vector3.zero; interiorHolder.transform.localRotation = Quaternion.identity; for (int v = 0; v < numberOfInteriorMeshes.Length; v++) { int numMeshes = numberOfInteriorMeshes[v]; for (int i = 0; i < numMeshes; i++) { string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; string filePath = DetailFolder + DetailFileName + FILE_EXTENTION; GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); interiorObject.name = INTERIOR_SUFFIX + VolumeSuffix + DetailSuffixIndex; interiorObject.transform.parent = interiorHolder.transform; interiorObject.transform.localPosition = Vector3.zero; interiorObject.transform.localRotation = Quaternion.identity; } } for (int v = 0; v < numberOfStairwells.Length; v++) { int numMeshes = numberOfStairwells[v]; for (int i = 0; i < numMeshes; i++) { string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; string filePath = DetailFolder + DetailFileName + FILE_EXTENTION; GameObject interiorObject = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(filePath)); interiorObject.name = STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; interiorObject.transform.parent = interiorHolder.transform; interiorObject.transform.localPosition = data.plan.volumes[v].stairBaseVector[i]; interiorObject.transform.localRotation = Quaternion.identity; } } } if (data.createPrefabOnExport) { string prefabPath = ROOT_FOLDER + data.exportFilename + "/" + data.exportFilename + ".prefab"; Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefab == null) { prefab = PrefabUtility.CreateEmptyPrefab(prefabPath); } PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab); } if (!data.placeIntoScene) { Object.DestroyImmediate(baseObject); } } if (data.exportLowLOD) { ExportLowLOD(data); } DYN_MESH = null; EXPORT_MESH = null; EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssets(); AssetDatabase.Refresh(); }catch (System.Exception e) { Debug.LogError("BuildR Export Error: " + e); EditorUtility.ClearProgressBar(); } }
private static void ExportModel(TrackBuildR track) { GameObject baseObject = new GameObject(track.exportFilename); baseObject.transform.position = CURRENT_TRANSFORM.position; baseObject.transform.rotation = CURRENT_TRANSFORM.rotation; EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f); track.ForceFullRecalculation(); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.1f); try { TrackBuildRTrack trackData = track.track; //check overwrites... string newDirectory = ROOT_FOLDER + track.exportFilename; if (!CreateFolder(newDirectory)) { EditorUtility.ClearProgressBar(); return; } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.15f); int numberOfCurves = trackData.numberOfCurves; float exportProgress = 0.75f / (numberOfCurves * 6.0f); ExportMaterial[] exportMaterials = new ExportMaterial[1]; ExportMaterial exportTexture = new ExportMaterial(); string[] dynNames = new [] { "track", "bumper", "boundary", "bottom", "offread", "trackCollider" }; for (int c = 0; c < numberOfCurves; c++) { TrackBuildRPoint curve = trackData[c]; int numberOfDynMeshes = 6; DynamicMeshGenericMultiMaterialMesh[] dynMeshes = new DynamicMeshGenericMultiMaterialMesh[6]; dynMeshes[0] = curve.dynamicTrackMesh; dynMeshes[1] = curve.dynamicBumperMesh; dynMeshes[2] = curve.dynamicBoundaryMesh; dynMeshes[3] = curve.dynamicBottomMesh; dynMeshes[4] = curve.dynamicOffroadMesh; dynMeshes[5] = curve.dynamicColliderMesh; int[] textureIndeices = new int[] { curve.trackTextureStyleIndex, curve.bumperTextureStyleIndex, curve.boundaryTextureStyleIndex, curve.bottomTextureStyleIndex, curve.offroadTextureStyleIndex, 0 }; for (int d = 0; d < numberOfDynMeshes; d++) { if (EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "Exporting Track Curve " + c + " " + dynNames[d], 0.15f + exportProgress * (c * 6 + d))) { EditorUtility.ClearProgressBar(); return; } DynamicMeshGenericMultiMaterialMesh exportDynMesh = dynMeshes[d]; if (track.includeTangents || exportDynMesh.isEmpty) { exportDynMesh.Build(track.includeTangents);//rebuild with tangents } TrackBuildRTexture texture = trackData.Texture(textureIndeices[d]); exportTexture.name = texture.customName; exportTexture.material = texture.material; exportTexture.generated = false; exportTexture.filepath = texture.filePath; exportMaterials[0] = exportTexture; int meshCount = exportDynMesh.meshCount; for (int i = 0; i < meshCount; i++) { Mesh exportMesh = exportDynMesh[i].mesh; MeshUtility.Optimize(exportMesh); string filenameSuffix = trackModelName(dynNames[d], c, (meshCount > 1) ? i : -1);// "trackCurve" + c + ((meshCount > 1) ? "_" + i.ToString() : ""); string filename = track.exportFilename + filenameSuffix; Export(filename, ROOT_FOLDER + track.exportFilename + "/", track, exportMesh, exportMaterials); if (track.createPrefabOnExport) { AssetDatabase.Refresh();//ensure the database is up to date... string modelFilePath = ROOT_FOLDER + track.exportFilename + "/" + filename + FILE_EXTENTION; if (d < numberOfDynMeshes - 1) { GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath)); newModel.name = filename; newModel.transform.parent = baseObject.transform; newModel.transform.localPosition = Vector3.zero; newModel.transform.localRotation = Quaternion.identity; } else { GameObject colliderObject = new GameObject("trackCollider"); colliderObject.AddComponent <MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(modelFilePath, typeof(Mesh)); colliderObject.transform.parent = baseObject.transform; colliderObject.transform.localPosition = Vector3.zero; colliderObject.transform.localRotation = Quaternion.identity; } } } } } if (track.createPrefabOnExport) { string prefabPath = ROOT_FOLDER + track.exportFilename + "/" + track.exportFilename + ".prefab"; Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefab == null) { prefab = PrefabUtility.CreateEmptyPrefab(prefabPath); } PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab); } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f); AssetDatabase.Refresh();//ensure the database is up to date... } catch (System.Exception e) { Debug.LogError("BuildR Export Error: " + e); EditorUtility.ClearProgressBar(); } Object.DestroyImmediate(baseObject); EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssets(); AssetDatabase.Refresh(); }
public void UpdateInteriors() { while (interiorMeshHolders.Count > 0) { GameObject destroyOld = interiorMeshHolders[0]; interiorMeshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } interiorMeshes.Clear(); if (data.renderInteriors) { int numberOfVolumes = data.plan.numberOfVolumes; for (int v = 0; v < numberOfVolumes; v++) { DynamicMeshGenericMultiMaterialMesh interiorMesh = new DynamicMeshGenericMultiMaterialMesh(); interiorMesh.subMeshCount = data.textures.Count; BuildrVolume volume = _data.plan.volumes[v]; BuildrInteriors.Build(interiorMesh, data, v); interiorMesh.Build(false); List <int> unusedInteriorTextures = interiorMesh.unusedSubmeshes; int numberOfInteriorMaterials = data.textures.Count; List <Material> interiorMaterials = new List <Material>(); for (int m = 0; m < numberOfInteriorMaterials; m++) { if (unusedInteriorTextures.Contains(m)) { continue;//skip, unused } BuildrTexture bTexture = data.textures[m]; interiorMaterials.Add(bTexture.usedMaterial); } int numberOfInteriorMeshes = interiorMesh.meshCount; for (int i = 0; i < numberOfInteriorMeshes; i++) { string meshName = "model interior"; if (numberOfVolumes > 0) { meshName += " volume " + (v + 1); } if (numberOfInteriorMeshes > 1) { meshName += " mesh " + (i + 1); } GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = Vector3.zero; meshFilt = newMeshHolder.AddComponent <MeshFilter>(); meshRend = newMeshHolder.AddComponent <MeshRenderer>(); meshFilt.mesh = interiorMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); int numberOfInterior = interiorMeshHolders.Count; for (int m = 0; m < numberOfInterior; m++) { meshRend.sharedMaterials = interiorMaterials.ToArray(); } } interiorMeshes.Add(interiorMesh); if (!volume.generateStairs) { continue; } DynamicMeshGenericMultiMaterialMesh stairwellMesh = new DynamicMeshGenericMultiMaterialMesh(); stairwellMesh.subMeshCount = data.textures.Count; BuildrStairs.Build(stairwellMesh, data, v, BuildrStairs.StairModes.Stepped, true); stairwellMesh.Build(false); List <int> unusedStairTextures = stairwellMesh.unusedSubmeshes; int numberOfStairMaterials = data.textures.Count; List <Material> stairMaterials = new List <Material>(); for (int m = 0; m < numberOfStairMaterials; m++) { if (unusedStairTextures.Contains(m)) { continue;//skip, unused } BuildrTexture bTexture = data.textures[m]; stairMaterials.Add(bTexture.usedMaterial); } int numberOfStairMeshes = stairwellMesh.meshCount; for (int i = 0; i < numberOfStairMeshes; i++) { string meshName = "model stairs"; if (numberOfVolumes > 0) { meshName += " volume " + (v + 1); } if (numberOfStairMeshes > 1) { meshName += " mesh " + (i + 1); } GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = volume.stairBaseVector[i]; meshFilt = newMeshHolder.AddComponent <MeshFilter>(); meshRend = newMeshHolder.AddComponent <MeshRenderer>(); meshFilt.mesh = stairwellMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); meshRend.sharedMaterials = stairMaterials.ToArray(); } interiorMeshes.Add(stairwellMesh); } } }
private static int[] ExportStairwells(BuildrData data) { int numberOfVolumes = data.plan.numberOfVolumes; int[] returnNumberOfMeshes = new int[numberOfVolumes]; for (int v = 0; v < numberOfVolumes; v++) { BuildrVolume volume = data.plan.volumes[v]; int numberOfUnpackedTextures = data.textures.Count; List<ExportMaterial> exportTextures = new List<ExportMaterial>(); if (!volume.generateStairs) continue; DynamicMeshGenericMultiMaterialMesh INT_STAIRWELL = new DynamicMeshGenericMultiMaterialMesh(); INT_STAIRWELL.subMeshCount = data.textures.Count; BuildrStairs.Build(INT_STAIRWELL, data, v, BuildrStairs.StairModes.Stepped, true); INT_STAIRWELL.Build(data.includeTangents); List<int> unusedStairTextures = INT_STAIRWELL.unusedSubmeshes; numberOfUnpackedTextures = data.textures.Count; for (int t = 0; t < numberOfUnpackedTextures; t++) { if (unusedStairTextures.Contains(t)) continue;//skip, unused ExportMaterial newTexture = new ExportMaterial(); newTexture.name = data.textures[t].name; newTexture.material = data.textures[t].material; newTexture.generated = false; newTexture.filepath = data.textures[t].filePath; exportTextures.Add(newTexture); } int numberOfStairMeshes = INT_STAIRWELL.meshCount; for (int i = 0; i < numberOfStairMeshes; i++) { MeshUtility.Optimize(INT_STAIRWELL[i].mesh); string VolumeSuffix = ((numberOfVolumes > 1) ? "_" + v : ""); string DetailSuffixIndex = ((numberOfStairMeshes > 1) ? "_" + i : ""); string DetailFileName = data.exportFilename + STAIR_SUFFIX + VolumeSuffix + DetailSuffixIndex; string DetailFolder = ROOT_FOLDER + data.exportFilename + "/"; Export(DetailFileName, DetailFolder, data, INT_STAIRWELL[i].mesh, exportTextures.ToArray()); } returnNumberOfMeshes[v] = numberOfStairMeshes; } return returnNumberOfMeshes; }
public void UpdateInteriors() { while (interiorMeshHolders.Count > 0) { GameObject destroyOld = interiorMeshHolders[0]; interiorMeshHolders.RemoveAt(0); DestroyImmediate(destroyOld); } interiorMeshes.Clear(); if (data.renderInteriors) { int numberOfVolumes = data.plan.numberOfVolumes; for(int v = 0; v < numberOfVolumes; v++) { DynamicMeshGenericMultiMaterialMesh interiorMesh = new DynamicMeshGenericMultiMaterialMesh(); interiorMesh.subMeshCount = data.textures.Count; BuildrVolume volume = _data.plan.volumes[v]; BuildrInteriors.Build(interiorMesh, data, v); interiorMesh.Build(false); List<int> unusedInteriorTextures = interiorMesh.unusedSubmeshes; int numberOfInteriorMaterials = data.textures.Count; List<Material> interiorMaterials = new List<Material>(); for (int m = 0; m < numberOfInteriorMaterials; m++) { if (unusedInteriorTextures.Contains(m)) continue;//skip, unused BuildrTexture bTexture = data.textures[m]; interiorMaterials.Add(bTexture.usedMaterial); } int numberOfInteriorMeshes = interiorMesh.meshCount; for (int i = 0; i < numberOfInteriorMeshes; i++) { string meshName = "model interior"; if (numberOfVolumes > 0) meshName += " volume " + (v + 1); if(numberOfInteriorMeshes>1)meshName += " mesh " + (i + 1); GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = Vector3.zero; meshFilt = newMeshHolder.AddComponent<MeshFilter>(); meshRend = newMeshHolder.AddComponent<MeshRenderer>(); meshFilt.mesh = interiorMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); int numberOfInterior = interiorMeshHolders.Count; for (int m = 0; m < numberOfInterior; m++) meshRend.sharedMaterials = interiorMaterials.ToArray(); } interiorMeshes.Add(interiorMesh); if(!volume.generateStairs) continue; DynamicMeshGenericMultiMaterialMesh stairwellMesh = new DynamicMeshGenericMultiMaterialMesh(); stairwellMesh.subMeshCount = data.textures.Count; BuildrStairs.Build(stairwellMesh, data, v, BuildrStairs.StairModes.Stepped, true); stairwellMesh.Build(false); List<int> unusedStairTextures = stairwellMesh.unusedSubmeshes; int numberOfStairMaterials = data.textures.Count; List<Material> stairMaterials = new List<Material>(); for (int m = 0; m < numberOfStairMaterials; m++) { if (unusedStairTextures.Contains(m)) continue;//skip, unused BuildrTexture bTexture = data.textures[m]; stairMaterials.Add(bTexture.usedMaterial); } int numberOfStairMeshes = stairwellMesh.meshCount; for (int i = 0; i < numberOfStairMeshes; i++) { string meshName = "model stairs"; if (numberOfVolumes > 0) meshName += " volume " + (v + 1); if (numberOfStairMeshes > 1) meshName += " mesh " + (i + 1); GameObject newMeshHolder = new GameObject(meshName); newMeshHolder.transform.parent = transform; newMeshHolder.transform.localPosition = volume.stairBaseVector[i]; meshFilt = newMeshHolder.AddComponent<MeshFilter>(); meshRend = newMeshHolder.AddComponent<MeshRenderer>(); meshFilt.mesh = stairwellMesh[i].mesh; interiorMeshHolders.Add(newMeshHolder); meshRend.sharedMaterials = stairMaterials.ToArray(); } interiorMeshes.Add(stairwellMesh); } } }
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();*/ }
/// <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();*/ }