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); } } }
/// <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();*/ }
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 }
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();*/ }