public static void ConformTrack(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float terrainHeightmapY = terrain.terrainData.heightmapScale.y; float terrainY = terrain.transform.position.y / terrainHeightmapY; float conformAccuracy = track.conformAccuracy; float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); Bounds trackBounds = new Bounds(); int numberOfCurves = track.numberOfCurves; for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; if (curve.holder == null) { continue; } Renderer[] rends = curve.holder.GetComponentsInChildren <Renderer>(); foreach (Renderer rend in rends) { trackBounds.Encapsulate(rend.bounds); } } Vector3 trackOffset = track.transform.position - terrain.transform.position; Vector3 trackScale = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z); int realNumberOfPoints = track.realNumberOfPoints; for (int i = 0; i < realNumberOfPoints; i++) { TrackBuildRPoint point = track[i]; Vector3 trackPointPosition = point.position; int pointX = Mathf.RoundToInt(((trackPointPosition.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int pointY = Mathf.RoundToInt(((trackPointPosition.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); pointX = Mathf.Clamp(pointX, 0, terrainWidth - 1); pointY = Mathf.Clamp(pointY, 0, terrainHeight - 1); trackPointPosition.y = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy; point.position = trackPointPosition; Vector3 controlPoint = point.forwardControlPoint; pointX = Mathf.RoundToInt(((controlPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); pointY = Mathf.RoundToInt(((controlPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); pointX = Mathf.Clamp(pointX, 0, terrainWidth - 1); pointY = Mathf.Clamp(pointY, 0, terrainHeight - 1); controlPoint.y = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy; point.forwardControlPoint = controlPoint; point.isDirty = true; } track.RecalculateCurves(); }
void OnEnable() { if (target != null) { _trackBuildR = (TrackBuildR)target; _track = _trackBuildR.track; } _stageToolbarTexturesA = new Texture2D[numberOfMenuOptionsA]; _stageToolbarTexturesA[0] = (Texture2D)Resources.Load("GUI/track"); _stageToolbarTexturesA[1] = (Texture2D)Resources.Load("GUI/boundary"); _stageToolbarTexturesA[2] = (Texture2D)Resources.Load("GUI/bumpers"); _stageToolbarTexturesA[3] = (Texture2D)Resources.Load("GUI/textures"); _stageToolbarTexturesA[4] = (Texture2D)Resources.Load("GUI/terrain"); _stageToolbarTexturesB = new Texture2D[numberOfMenuOptionsB]; _stageToolbarTexturesB[0] = (Texture2D)Resources.Load("GUI/stunt"); _stageToolbarTexturesB[1] = (Texture2D)Resources.Load("GUI/diagram"); _stageToolbarTexturesB[2] = (Texture2D)Resources.Load("GUI/options"); _stageToolbarTexturesB[3] = (Texture2D)Resources.Load("GUI/export"); //Preview Camera if (_trackBuildR.trackEditorPreview != null) DestroyImmediate(_trackBuildR.trackEditorPreview); if (!EditorApplication.isPlaying && SystemInfo.supportsRenderTextures) { _trackBuildR.trackEditorPreview = new GameObject("Track Preview Cam"); _trackBuildR.trackEditorPreview.hideFlags = HideFlags.HideAndDontSave; _trackBuildR.trackEditorPreview.AddComponent<Camera>(); _trackBuildR.trackEditorPreview.GetComponent<Camera>().fieldOfView = 80; _trackBuildR.trackEditorPreview.GetComponent<Camera>().depth = -99999; //Retreive camera settings from the main camera Camera[] cams = Camera.allCameras; bool sceneHasCamera = cams.Length > 0; Camera sceneCamera = null; Skybox sceneCameraSkybox = null; if (Camera.main) { sceneCamera = Camera.main; } else if (sceneHasCamera) { sceneCamera = cams[0]; } if (sceneCamera != null) if (sceneCameraSkybox == null) sceneCameraSkybox = sceneCamera.GetComponent<Skybox>(); if (sceneCamera != null) { _trackBuildR.trackEditorPreview.GetComponent<Camera>().backgroundColor = sceneCamera.backgroundColor; if (sceneCameraSkybox != null) _trackBuildR.trackEditorPreview.AddComponent<Skybox>().material = sceneCameraSkybox.material; else if (RenderSettings.skybox != null) _trackBuildR.trackEditorPreview.AddComponent<Skybox>().material = RenderSettings.skybox; } } }
public void Init() { track = gameObject.AddComponent <TrackBuildRTrack>(); track.InitTextures(); track.baseTransform = transform; TrackBuildRPoint p0 = gameObject.AddComponent <TrackBuildRPoint>(); // ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p1 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p2 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p3 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>(); p0.baseTransform = transform; p1.baseTransform = transform; p2.baseTransform = transform; p3.baseTransform = transform; p0.position = new Vector3(-20, 0, -20); p1.position = new Vector3(20, 0, -20); p2.position = new Vector3(20, 0, 20); p3.position = new Vector3(-20, 0, 20); p0.forwardControlPoint = new Vector3(0, 0, -20); p1.forwardControlPoint = new Vector3(40, 0, -20); p2.forwardControlPoint = new Vector3(0, 0, 20); p3.forwardControlPoint = new Vector3(-40, 0, 20); p0.leftForwardControlPoint = new Vector3(-15, 0, -20); p1.leftForwardControlPoint = new Vector3(25, 0, -20); p2.leftForwardControlPoint = new Vector3(5, 0, 20); p3.leftForwardControlPoint = new Vector3(-35, 0, 20); p0.rightForwardControlPoint = new Vector3(15, 0, -20); p1.rightForwardControlPoint = new Vector3(55, 0, -20); p2.rightForwardControlPoint = new Vector3(-5, 0, 20); p3.rightForwardControlPoint = new Vector3(-45, 0, 20); track.AddPoint(p0); track.AddPoint(p1); track.AddPoint(p2); track.AddPoint(p3); generator = gameObject.AddComponent <TrackBuildRGenerator>(); ForceFullRecalculation(); track.diagramMesh = new Mesh(); track.diagramMesh.vertices = new [] { new Vector3(-1, 0, -1), new Vector3(1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, 1) }; track.diagramMesh.uv = new [] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) }; track.diagramMesh.triangles = new [] { 1, 0, 2, 1, 2, 3 }; track.diagramGO = new GameObject("Diagram"); track.diagramGO.transform.parent = transform; track.diagramGO.transform.localPosition = Vector3.zero; track.diagramGO.AddComponent <MeshFilter>().mesh = track.diagramMesh; track.diagramMaterial = new Material(Shader.Find("Unlit/Texture")); track.diagramGO.AddComponent <MeshRenderer>().material = track.diagramMaterial; track.diagramGO.AddComponent <MeshCollider>().sharedMesh = track.diagramMesh; }
/// <summary> /// unfinished! /// </summary> /// <param name="track"></param> /// <param name="selectedPoint"></param> public static void AddTwist(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength); Vector3 twistDirection = atPoint.trackDirection; Vector3 twistMiddle = atPoint.worldPosition; Vector3 twistUp = atPoint.trackUp; Vector3 twistAxis = Vector3.Cross(twistDirection, twistUp); float twistRadius = track.twistRadius; Vector3 twistStartPosition = -twistDirection * (twistDistance * 0.33f); Vector3 twistEndPosition = twistDirection * (twistDistance * 0.33f); Vector3 twistCentreHeight = twistUp * twistRadius; Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp); Vector3 twistCenter = atPoint.worldPosition + Vector3.up * twistRadius; float controlPointLength = twistRadius / (Mathf.PI); int numberOfPoints = track.twistPoints; float arcPercent = 1.0f / numberOfPoints; TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints + 1]; for (int i = 0; i < numberOfPoints; i++) { float pointArcPercent = arcPercent * i; float radA = Mathf.PI * 2 * (pointArcPercent + 0.5f); Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius); float smoothI = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent); Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI)); Vector3 pointPosition = (pointLoopPosition) + lateral; Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, twistAxis).normalized; TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i); newTrackPoint.worldPosition = twistCenter + pointPosition; newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection); newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength); loopPoints[i] = newTrackPoint; } atPoint.worldPosition += twistStartPosition; atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection); atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis; loopPoints[6] = atPoint; // _trackBuildR.pointMode = TrackBuildR.pointModes.transform; for (int i = 0; i < numberOfPoints + 1; i++) { loopPoints[i].extrudeTrack = true; loopPoints[i].extrudeTrackBottom = true; loopPoints[i].extrudeLength = 0.5f; loopPoints[i].RecalculateStoredValues(); } }
public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex) { TrackBuildRPoint atPoint = track[selectedPointIndex]; int atPointIndex = selectedPointIndex; float loopRadius = track.loopRadius; float trackWidth = atPoint.width; Vector3 trackDirection = atPoint.trackDirection.normalized; Vector3 trackUp = atPoint.trackUpQ * Vector3.forward; Vector3 trackCross = atPoint.trackCross; Vector3 entryPosition = atPoint.worldPosition + (trackCross * trackWidth * 0.6f); Vector3 loopAxis = Vector3.Cross(trackDirection, trackUp); Vector3 loopCenter = atPoint.worldPosition + Vector3.up * loopRadius; Quaternion loopAngle = Quaternion.FromToRotation(Vector3.right, trackDirection); float controlPointLength = loopRadius / (Mathf.PI); Vector3 controlPointLateral = -loopAxis; int numberOfPoints = 6; float arcPercent = 1.0f / numberOfPoints; TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7]; for (int i = 0; i < numberOfPoints; i++) { float pointArcPercent = arcPercent * i; TrackBuildRPoint newTrackPoint = track.InsertPoint(atPointIndex + 1); float rad = Mathf.PI * 2 * (pointArcPercent + 0.5f); Vector3 pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius); Vector3 lateral = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent); Vector3 pointPosition = (pointLoopPosition) + lateral; Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, loopAxis).normalized; newTrackPoint.worldPosition = loopCenter + pointPosition; newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection); newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral; loopPoints[i] = newTrackPoint; } atPoint.worldPosition = entryPosition; atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection); atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral; loopPoints[6] = atPoint; // _trackBuildR.pointMode = TrackBuildR.pointModes.transform; for (int i = 0; i < numberOfPoints + 1; i++) { loopPoints[i].extrudeTrack = true; loopPoints[i].extrudeTrackBottom = true; loopPoints[i].extrudeLength = 0.5f; loopPoints[i].RecalculateStoredValues(); } }
public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex) { TrackBuildRPoint atPoint = track[selectedPointIndex]; int atPointIndex = selectedPointIndex; float loopRadius = track.loopRadius; float trackWidth = atPoint.width; Vector3 trackDirection = atPoint.trackDirection.normalized; Vector3 trackUp = atPoint.trackUpQ * Vector3.forward; Vector3 trackCross = atPoint.trackCross; Vector3 entryPosition = atPoint.worldPosition + (trackCross * trackWidth * 0.6f); Vector3 loopAxis = Vector3.Cross(trackDirection, trackUp); Vector3 loopCenter = atPoint.worldPosition + Vector3.up * loopRadius; Quaternion loopAngle = Quaternion.FromToRotation(Vector3.right, trackDirection); float controlPointLength = loopRadius / (Mathf.PI); Vector3 controlPointLateral = -loopAxis; int numberOfPoints = 6; float arcPercent = 1.0f / numberOfPoints; TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7]; for (int i = 0; i < numberOfPoints; i++) { float pointArcPercent = arcPercent * i; TrackBuildRPoint newTrackPoint = track.InsertPoint(atPointIndex + 1); float rad = Mathf.PI * 2 * (pointArcPercent + 0.5f); Vector3 pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius); Vector3 lateral = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent); Vector3 pointPosition = (pointLoopPosition) + lateral; Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, loopAxis).normalized; newTrackPoint.worldPosition = loopCenter + pointPosition; newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection); newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral; loopPoints[i] = newTrackPoint; } atPoint.worldPosition = entryPosition; atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection); atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral; loopPoints[6] = atPoint; // _trackBuildR.pointMode = TrackBuildR.pointModes.transform; for (int i = 0; i < numberOfPoints + 1; i++) { loopPoints[i].extrudeTrack = true; loopPoints[i].extrudeTrackBottom = true; loopPoints[i].extrudeLength = 0.5f; loopPoints[i].RecalculateStoredValues(); } }
public static void AddJumpTwist(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1); float trackPartDistance = lastPoint.arcLength + atPoint.arcLength; float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength); float trackWidth = atPoint.width * 0.5f; Vector3 startCross = atPoint.trackCross; Vector3 jumpDirection = atPoint.trackDirection; Vector3 jumpMiddle = atPoint.worldPosition; Quaternion atPointUpQ = atPoint.trackUpQ; Quaternion trackUpJump = Quaternion.AngleAxis(track.twistAngle, -jumpDirection); Quaternion trackCrossExit = trackUpJump * (atPointUpQ); Quaternion trackCrossEntry = Quaternion.Inverse(trackUpJump) * (atPointUpQ); Vector3 jumpLateral = startCross * track.twistAngle / 33.3f; Vector3 jumpHeight = atPointUpQ * (Vector3.forward * track.jumpHeight); Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f) + jumpHeight - jumpLateral; Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f) + jumpHeight + jumpLateral; lastPoint.extrudeTrack = true; lastPoint.extrudeLength = track.jumpHeight; lastPoint.extrudeCurveEnd = true; lastPoint.extrudeTrackBottom = true; atPoint.Reset(); atPoint.worldPosition = jumpStartPosition; atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight; atPoint.trackUpQ = trackCrossExit; atPoint.render = false; TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1); jumpEnd.worldPosition = jumpEndPosition; jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition - jumpHeight; jumpEnd.trackUpQ = trackCrossEntry; jumpEnd.extrudeTrack = true; jumpEnd.extrudeLength = track.jumpHeight; jumpEnd.extrudeCurveEnd = true; jumpEnd.extrudeTrackBottom = true; atPoint.RecalculateStoredValues(); jumpEnd.RecalculateStoredValues(); }
public static void ResetTerrain(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float[,] tData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); for (int x = 0; x < terrainWidth; x++) { for (int y = 0; y < terrainHeight; y++) { tData[x, y] = 1; } } terrainData.SetHeights(0, 0, tData); terrain.terrainData = terrainData; }
public void Start() { //find nearest curve trackData = track.track; float nearestCurveDistance = Mathf.Infinity; int numberOfCurves = trackData.numberOfCurves; for (int i = 0; i < numberOfCurves; i++) { Vector3 curveCenter = trackData[i].center; float thisDistance = (curveCenter - transform.position).sqrMagnitude; if (thisDistance < nearestCurveDistance) { // curveIndex = i; nearestCurveDistance = thisDistance; } } // TrackBuildRCurve curve = trackData.Curve(curveIndex); }
public static void AddJump(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1); float trackPartDistance = lastPoint.arcLength + atPoint.arcLength; float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength); Vector3 jumpDirection = atPoint.trackDirection; Vector3 jumpMiddle = atPoint.worldPosition; Vector3 startCross = atPoint.trackCross; float trackWidth = atPoint.width * 0.5f; Quaternion trackUp = atPoint.trackUpQ; Vector3 jumpHeight = trackUp * (Vector3.forward * track.jumpHeight); Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f); Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f); lastPoint.extrudeTrack = true; lastPoint.extrudeLength = track.jumpHeight; lastPoint.extrudeCurveEnd = true; atPoint.Reset(); atPoint.worldPosition = jumpStartPosition + jumpHeight; atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight * 2; atPoint.trackUpQ = trackUp; atPoint.render = false; TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1); jumpEnd.worldPosition = jumpEndPosition + jumpHeight; jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition; jumpEnd.trackUpQ = trackUp; jumpEnd.extrudeTrack = true; jumpEnd.extrudeLength = track.jumpHeight; jumpEnd.extrudeCurveEnd = true; atPoint.RecalculateStoredValues(); jumpEnd.RecalculateStoredValues(); }
public static void AddJump(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); // TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1); float trackPartDistance = lastPoint.arcLength + atPoint.arcLength; float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength); Vector3 jumpDirection = atPoint.trackDirection; Vector3 jumpMiddle = atPoint.worldPosition; // Vector3 startCross = atPoint.trackCross; // float trackWidth = atPoint.width * 0.5f; Quaternion trackUp = atPoint.trackUpQ; Vector3 jumpHeight = trackUp * (Vector3.forward * track.jumpHeight); Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f); Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f); lastPoint.extrudeTrack = true; lastPoint.extrudeLength = track.jumpHeight; lastPoint.extrudeCurveEnd = true; atPoint.Reset(); atPoint.worldPosition = jumpStartPosition + jumpHeight; atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight * 2; atPoint.trackUpQ = trackUp; atPoint.render = false; TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1); jumpEnd.worldPosition = jumpEndPosition + jumpHeight; jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition; jumpEnd.trackUpQ = trackUp; jumpEnd.extrudeTrack = true; jumpEnd.extrudeLength = track.jumpHeight; jumpEnd.extrudeCurveEnd = true; atPoint.RecalculateStoredValues(); jumpEnd.RecalculateStoredValues(); }
public static void MergeTerrain(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float terrainHeightmapY = terrain.terrainData.heightmapScale.y; float terrainY = terrain.transform.position.y / terrainHeightmapY; Vector3 meshScale = terrainData.heightmapScale; float terrainAccuracy = track.terrainAccuracy; float terrainMergeMargin = track.terrainMergeMargin; float trackY = track.transform.position.y; float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); float[,] mergeData = new float[terrainWidth, terrainHeight]; float[,] modifiedData = new float[terrainWidth, terrainHeight]; int[,] modifiedPointLock = new int[terrainWidth, terrainHeight]; Bounds trackBounds = new Bounds(); int numberOfCurves = track.numberOfCurves; for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; if(curve.holder == null) continue; Renderer[] rends = curve.holder.GetComponentsInChildren<Renderer>(); foreach (Renderer rend in rends) { trackBounds.Encapsulate(rend.bounds); } } Vector3 trackOffset = track.transform.position - terrain.transform.position; Vector3 trackScale = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z); float mergeWidth = track.terrainMergeWidth; AnimationCurve mergeCurve = track.mergeCurve; float minScaleUnit = Mathf.Min(meshScale.x, meshScale.z); Vector3 trackHeightMod = new Vector3(0,trackY,0); for(int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; int storedPointSize = curve.storedPointSize; for(int p = 0; p < storedPointSize-1; p++) { Vector3 pointA = curve.sampledPoints[p] + trackHeightMod; Vector3 pointB = curve.sampledPoints[p + 1] + trackHeightMod; Vector3 crossA = curve.sampledTrackCrosses[p]; Vector3 crossB = curve.sampledTrackCrosses[p+1]; float widthA = curve.sampledWidths[p] * terrainMergeMargin; float widthB = curve.sampledWidths[p + 1] * terrainMergeMargin; // float heightA = (pointA.y - terrainAccuracy) * trackScale.y - terrainY; // float heightB = (pointB.y - terrainAccuracy) * trackScale.y - terrainY; Vector3 lpointA = (pointA - crossA * (widthA + mergeWidth)); Vector3 rpointA = (pointA + crossA * (widthA + mergeWidth)); Vector3 lpointB = (pointB - crossB * (widthB + mergeWidth)); Vector3 rpointB = (pointB + crossB * (widthB + mergeWidth)); float crownA = curve.sampledCrowns[p] - terrainAccuracy; float crownB = curve.sampledCrowns[p + 1] - terrainAccuracy; float pointDistanceLeft = Vector3.Distance(lpointA, lpointB) * 1.8f; float pointDistanceRight = Vector3.Distance(rpointA, rpointB) * 1.8f; float pointDistance = Mathf.Max(pointDistanceLeft, pointDistanceRight); float pointFillResolution = minScaleUnit/ pointDistance * 0.125f; float heightLA = (lpointA.y - terrainAccuracy) * trackScale.y - terrainY; float heightRA = (rpointA.y - terrainAccuracy) * trackScale.y - terrainY; float heightLB = (lpointB.y - terrainAccuracy) * trackScale.y - terrainY; float heightRB = (rpointB.y - terrainAccuracy) * trackScale.y - terrainY; for (float pf = 0; pf < 1; pf += pointFillResolution)//point a to point b { //Track Filler Vector3 fillPoint = Vector3.Lerp(pointA, pointB, pf); Vector3 fillCross = Vector3.Lerp(crossA, crossB, pf); float fillWidth = Mathf.Lerp(widthA, widthB, pf);// *1.2f; float fillCrown = Mathf.Lerp(crownA, crownB, pf);// *1.2f; float fillTrackHeightL = Mathf.Lerp(heightLA, heightLB, pf); float fillTrackHeightR = Mathf.Lerp(heightRA, heightRB, pf); Vector3 leftTrackPoint = fillPoint - fillCross * fillWidth; Vector3 rightTrackPoint = fillPoint + fillCross * fillWidth; int leftX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int rightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int diffX = leftX - rightX; int diffY = leftY - rightY; int trackCrossFillAmount = Mathf.Max(Mathf.Abs(diffX),1) * Mathf.Max(Mathf.Abs(diffY),1); for (int f = 0; f < trackCrossFillAmount; f++)//left to right { float move = f / (float)trackCrossFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(leftX, rightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(leftY, rightY, move)); if(fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) continue; float crownHeight = Mathf.Sin(move * Mathf.PI) * fillCrown / terrainHeightmapY; float fillTrackHeight = Mathf.Lerp(fillTrackHeightL, fillTrackHeightR, move) + crownHeight; int currentPointLock = modifiedPointLock[fillY, fillX]; if (currentPointLock == 0 || mergeData[fillY, fillX] > fillTrackHeight) mergeData[fillY, fillX] = fillTrackHeight; modifiedPointLock[fillY, fillX] = 1;//point lock } //Merge Vector3 leftMergePoint = leftTrackPoint - fillCross * mergeWidth; int leftMergeLeftX = Mathf.RoundToInt(((leftMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftMergeLeftY = Mathf.RoundToInt(((leftMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int leftMergeRightX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftMergeRightY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); // int leftMergeDiffX = leftMergeLeftX - leftMergeRightX; int leftMergeDiffY = leftMergeLeftY - leftMergeRightY; int leftMergeFillAmount = Mathf.Max(Mathf.Abs(leftMergeDiffX), 1) * Mathf.Max(Mathf.Abs(leftMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY)); for (int f = 0; f < leftMergeFillAmount; f++) { float move = f / (float)leftMergeFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftX, leftMergeRightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftY, leftMergeRightY, move)); if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) continue; float curveStrength = mergeCurve.Evaluate(move); float fillTrackHeight = fillTrackHeightL; float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength); int pointLock = modifiedPointLock[fillY, fillX]; float currentMergeHeight = mergeData[fillY, fillX]; float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight); float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight); if (newDifference < currentDifference && pointLock == 0) { mergeData[fillY, fillX] = mergeHeight; } } Vector3 rightMergePoint = rightTrackPoint + fillCross * mergeWidth; int rightMergeLeftX = Mathf.RoundToInt(((rightMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightMergeLeftY = Mathf.RoundToInt(((rightMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int rightMergeRightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightMergeRightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); // int rightMergeDiffX = rightMergeLeftX - rightMergeRightX; int rightMergeDiffY = rightMergeLeftY - rightMergeRightY; int rightMergeFillAmount = Mathf.Max(Mathf.Abs(rightMergeDiffX),1) * Mathf.Max(Mathf.Abs(rightMergeDiffY),1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY)); for (int f = 0; f < rightMergeFillAmount; f++) { float move = f / (float)rightMergeFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftX, rightMergeRightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftY, rightMergeRightY, move)); if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) continue; float curveStrength = mergeCurve.Evaluate(move); float fillTrackHeight = fillTrackHeightR; float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength); int pointLock = modifiedPointLock[fillY, fillX]; float currentMergeHeight = mergeData[fillY, fillX]; float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight); float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight); if (newDifference < currentDifference && pointLock == 0) { mergeData[fillY, fillX] = mergeHeight; } } } } } for(int x = 0; x < terrainWidth; x++) { for(int y = 0; y < terrainHeight; y++) { bool isNotEdge = x > 0 && x < terrainWidth-1 && y > 0 && y < terrainHeight-1; if (mergeData[x, y] == 0) { int mergeNeighbours = 0; if(isNotEdge) { mergeNeighbours += (mergeData[x+1, y] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x-1, y] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x, y+1] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x, y-1] != 0) ? 1 : 0; } if(mergeNeighbours > 1)//if a hole is surounded by rasied terrain in two or more neighbouring places { float mergeHeight = 0; mergeHeight += (mergeData[x + 1, y] != 0) ? mergeData[x + 1, y] : 0; mergeHeight += (mergeData[x - 1, y] != 0) ? mergeData[x - 1, y] : 0; mergeHeight += (mergeData[x, y + 1] != 0) ? mergeData[x, y + 1] : 0; mergeHeight += (mergeData[x, y - 1] != 0) ? mergeData[x, y - 1] : 0; modifiedData[x, y] = mergeHeight / mergeNeighbours;//clean up holes } else { modifiedData[x, y] = originalData[x, y];//use original } } else { modifiedData[x, y] = mergeData[x, y]; } } } terrainData.SetHeights(0, 0, modifiedData); terrain.terrainData = terrainData; }
public static void MergeTerrain(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float terrainHeightmapY = terrain.terrainData.heightmapScale.y; float terrainY = terrain.transform.position.y / terrainHeightmapY; Vector3 meshScale = terrainData.heightmapScale; float terrainAccuracy = track.terrainAccuracy; float terrainMergeMargin = track.terrainMergeMargin; float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); float[,] mergeData = new float[terrainWidth, terrainHeight]; float[,] modifiedData = new float[terrainWidth, terrainHeight]; int[,] modifiedPointLock = new int[terrainWidth, terrainHeight]; Bounds trackBounds = new Bounds(); int numberOfCurves = track.numberOfCurves; for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; if (curve.holder == null) { continue; } Renderer[] rends = curve.holder.GetComponentsInChildren <Renderer>(); foreach (Renderer rend in rends) { trackBounds.Encapsulate(rend.bounds); } } Vector3 trackOffset = track.transform.position - terrain.transform.position; Vector3 trackScale = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z); float mergeWidth = track.terrainMergeWidth; AnimationCurve mergeCurve = track.mergeCurve; float minScaleUnit = Mathf.Min(meshScale.x, meshScale.z); for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; int storedPointSize = curve.storedPointSize; for (int p = 0; p < storedPointSize - 1; p++) { Vector3 pointA = curve.sampledPoints[p]; Vector3 pointB = curve.sampledPoints[p + 1]; Vector3 crossA = curve.sampledTrackCrosses[p]; Vector3 crossB = curve.sampledTrackCrosses[p + 1]; float widthA = curve.sampledWidths[p] * terrainMergeMargin; float widthB = curve.sampledWidths[p + 1] * terrainMergeMargin; // float heightA = (pointA.y - terrainAccuracy) * trackScale.y - terrainY; // float heightB = (pointB.y - terrainAccuracy) * trackScale.y - terrainY; Vector3 lpointA = (pointA - crossA * (widthA + mergeWidth)); Vector3 rpointA = (pointA + crossA * (widthA + mergeWidth)); Vector3 lpointB = (pointB - crossB * (widthB + mergeWidth)); Vector3 rpointB = (pointB + crossB * (widthB + mergeWidth)); float crownA = curve.sampledCrowns[p] - terrainAccuracy; float crownB = curve.sampledCrowns[p + 1] - terrainAccuracy; float pointDistanceLeft = Vector3.Distance(lpointA, lpointB) * 1.8f; float pointDistanceRight = Vector3.Distance(rpointA, rpointB) * 1.8f; float pointDistance = Mathf.Max(pointDistanceLeft, pointDistanceRight); float pointFillResolution = minScaleUnit / pointDistance * 0.125f; float heightLA = (lpointA.y - terrainAccuracy) * trackScale.y - terrainY; float heightRA = (rpointA.y - terrainAccuracy) * trackScale.y - terrainY; float heightLB = (lpointB.y - terrainAccuracy) * trackScale.y - terrainY; float heightRB = (rpointB.y - terrainAccuracy) * trackScale.y - terrainY; for (float pf = 0; pf < 1; pf += pointFillResolution)//point a to point b { //Track Filler Vector3 fillPoint = Vector3.Lerp(pointA, pointB, pf); Vector3 fillCross = Vector3.Lerp(crossA, crossB, pf); float fillWidth = Mathf.Lerp(widthA, widthB, pf); // *1.2f; float fillCrown = Mathf.Lerp(crownA, crownB, pf); // *1.2f; float fillTrackHeightL = Mathf.Lerp(heightLA, heightLB, pf); float fillTrackHeightR = Mathf.Lerp(heightRA, heightRB, pf); Vector3 leftTrackPoint = fillPoint - fillCross * fillWidth; Vector3 rightTrackPoint = fillPoint + fillCross * fillWidth; int leftX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int rightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int diffX = leftX - rightX; int diffY = leftY - rightY; int trackCrossFillAmount = Mathf.Max(Mathf.Abs(diffX), 1) * Mathf.Max(Mathf.Abs(diffY), 1); for (int f = 0; f < trackCrossFillAmount; f++)//left to right { float move = f / (float)trackCrossFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(leftX, rightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(leftY, rightY, move)); if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) { continue; } float crownHeight = Mathf.Sin(move * Mathf.PI) * fillCrown / terrainHeightmapY; float fillTrackHeight = Mathf.Lerp(fillTrackHeightL, fillTrackHeightR, move) + crownHeight; int currentPointLock = modifiedPointLock[fillY, fillX]; if (currentPointLock == 0 || mergeData[fillY, fillX] > fillTrackHeight) { mergeData[fillY, fillX] = fillTrackHeight; } modifiedPointLock[fillY, fillX] = 1;//point lock } //Merge Vector3 leftMergePoint = leftTrackPoint - fillCross * mergeWidth; int leftMergeLeftX = Mathf.RoundToInt(((leftMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftMergeLeftY = Mathf.RoundToInt(((leftMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int leftMergeRightX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int leftMergeRightY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); // int leftMergeDiffX = leftMergeLeftX - leftMergeRightX; int leftMergeDiffY = leftMergeLeftY - leftMergeRightY; int leftMergeFillAmount = Mathf.Max(Mathf.Abs(leftMergeDiffX), 1) * Mathf.Max(Mathf.Abs(leftMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY)); for (int f = 0; f < leftMergeFillAmount; f++) { float move = f / (float)leftMergeFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftX, leftMergeRightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftY, leftMergeRightY, move)); if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) { continue; } float curveStrength = mergeCurve.Evaluate(move); float fillTrackHeight = fillTrackHeightL; float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength); int pointLock = modifiedPointLock[fillY, fillX]; float currentMergeHeight = mergeData[fillY, fillX]; float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight); float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight); if (newDifference < currentDifference && pointLock == 0) { mergeData[fillY, fillX] = mergeHeight; } } Vector3 rightMergePoint = rightTrackPoint + fillCross * mergeWidth; int rightMergeLeftX = Mathf.RoundToInt(((rightMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightMergeLeftY = Mathf.RoundToInt(((rightMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); int rightMergeRightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int rightMergeRightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); // int rightMergeDiffX = rightMergeLeftX - rightMergeRightX; int rightMergeDiffY = rightMergeLeftY - rightMergeRightY; int rightMergeFillAmount = Mathf.Max(Mathf.Abs(rightMergeDiffX), 1) * Mathf.Max(Mathf.Abs(rightMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY)); for (int f = 0; f < rightMergeFillAmount; f++) { float move = f / (float)rightMergeFillAmount; int fillX = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftX, rightMergeRightX, move)); int fillY = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftY, rightMergeRightY, move)); if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight) { continue; } float curveStrength = mergeCurve.Evaluate(move); float fillTrackHeight = fillTrackHeightR; float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength); int pointLock = modifiedPointLock[fillY, fillX]; float currentMergeHeight = mergeData[fillY, fillX]; float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight); float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight); if (newDifference < currentDifference && pointLock == 0) { mergeData[fillY, fillX] = mergeHeight; } } } } } for (int x = 0; x < terrainWidth; x++) { for (int y = 0; y < terrainHeight; y++) { bool isNotEdge = x > 0 && x < terrainWidth - 1 && y > 0 && y < terrainHeight - 1; if (mergeData[x, y] == 0) { int mergeNeighbours = 0; if (isNotEdge) { mergeNeighbours += (mergeData[x + 1, y] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x - 1, y] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x, y + 1] != 0) ? 1 : 0; mergeNeighbours += (mergeData[x, y - 1] != 0) ? 1 : 0; } if (mergeNeighbours > 1)//if a hole is surounded by rasied terrain in two or more neighbouring places { float mergeHeight = 0; mergeHeight += (mergeData[x + 1, y] != 0) ? mergeData[x + 1, y] : 0; mergeHeight += (mergeData[x - 1, y] != 0) ? mergeData[x - 1, y] : 0; mergeHeight += (mergeData[x, y + 1] != 0) ? mergeData[x, y + 1] : 0; mergeHeight += (mergeData[x, y - 1] != 0) ? mergeData[x, y - 1] : 0; modifiedData[x, y] = mergeHeight / mergeNeighbours;//clean up holes } else { modifiedData[x, y] = originalData[x, y];//use original } } else { modifiedData[x, y] = mergeData[x, y]; } } } terrainData.SetHeights(0, 0, modifiedData); terrain.terrainData = terrainData; }
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 static void InspectorGUI(TrackBuildR track) { TrackBuildRTrack trackData = track.track; const int guiWidth = 400; const int textWidth = 348; const int toggleWidth = 25; const int helpWidth = 20; CURRENT_TRANSFORM = track.transform; EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Filename", GUILayout.Width(225)); track.exportFilename = EditorGUILayout.TextField(track.exportFilename, GUILayout.Width(175)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Filetype", GUILayout.Width(350)); track.fileType = (TrackBuildR.fileTypes)EditorGUILayout.EnumPopup(track.fileType, GUILayout.Width(50)); switch (track.fileType) { case TrackBuildR.fileTypes.Obj: FILE_EXTENTION = ".obj"; break; case TrackBuildR.fileTypes.Fbx: FILE_EXTENTION = ".fbx"; break; } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Copy Textures into Export Folder", GUILayout.Width(textWidth)); track.copyTexturesIntoExportFolder = EditorGUILayout.Toggle(track.copyTexturesIntoExportFolder, GUILayout.Width(toggleWidth)); if (GUILayout.Button("?", GUILayout.Width(helpWidth))) { string helpTitle = "Help - Copy Textures into Export Folder"; string helpBody = "Check this box if you want to copy the textures you are using into the export folder." + "\nThis is useful if you plan to use the exported model elsewhere. Having the model and the textures in one folder will allow you to move this model with ease."; EditorUtility.DisplayDialog(helpTitle, helpBody, "close"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Export Collider"); // track.exportSimpleCollider = EditorGUILayout.Toggle(track.exportSimpleCollider, GUILayout.Width(toggleWidth)); track.exportCollider = EditorGUILayout.Toggle(track.exportCollider, GUILayout.Width(toggleWidth)); if (GUILayout.Button("?", GUILayout.Width(helpWidth))) { string helpTitle = "Help - Export Collider Mesh"; string helpBody = "Check this box if you wish to generate a trackCollider mesh for your model." + "\nThis will generate a mesh to be used with colliders."; EditorUtility.DisplayDialog(helpTitle, helpBody, "close"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Export as Prefab", GUILayout.Width(textWidth)); track.createPrefabOnExport = EditorGUILayout.Toggle(track.createPrefabOnExport, GUILayout.Width(toggleWidth)); if (GUILayout.Button("?", GUILayout.Width(helpWidth))) { string helpTitle = "Help - Export as Prefab"; string helpBody = "Select this if you wish to create a prefab of your model." + "\nThis is recommended if you're exporting a trackCollider so they will get packaged together."; EditorUtility.DisplayDialog(helpTitle, helpBody, "close"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); bool usingSubstances = false; int numberOfTextures = trackData.numberOfTextures; for (int i = 0; i < numberOfTextures; i++) { TrackBuildRTexture texture = trackData.Texture(i); if (texture.type == TrackBuildRTexture.Types.Substance) { usingSubstances = true; break; } } if (usingSubstances) { EditorGUILayout.HelpBox("Model uses Substance textures." + "\nExporting model to " + track.fileType + " will lose references to this texture and it will be rendered white.", MessageType.Warning); } if (GUILayout.Button("Export", GUILayout.Width(guiWidth), GUILayout.Height(40))) { ExportModel(track); } EditorGUILayout.Space(); if (GUILayout.Button("Export to XML")) { string defaultName = track.name; defaultName.Replace(" ", "_"); string filepath = EditorUtility.SaveFilePanel("Export Track BuildR Track to XML", "Assets/TrackBuildR", defaultName, "xml"); if (filepath != "") { using (StreamWriter sw = new StreamWriter(filepath)) { sw.Write(track.ToXML());//write out contents of data to XML } } AssetDatabase.Refresh(); } if (GUILayout.Button("Import from XML")) { string xmlpath = EditorUtility.OpenFilePanel("Import Track BuildR Track from XML", "Assets/TrackBuildR/", "xml"); if (xmlpath != "") { track.FromXML(xmlpath); } } if (GUILayout.Button("Import from KML")) { string xmlpath = EditorUtility.OpenFilePanel("Import Google Earth KML", "Assets/TrackBuildR/", "kml"); if (xmlpath != "") { track.FromKML(xmlpath); } } CURRENT_TRANSFORM = null; }
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; int numberOfDynMeshes = 9; float exportProgress = 0.75f / (numberOfCurves * numberOfDynMeshes); ExportMaterial[] exportMaterials = new ExportMaterial[1]; ExportMaterial exportTexture = new ExportMaterial(); TrackBuildRTexture[] textures = trackData.GetTexturesArray(); int textureCount = textures.Length; Material[] materials = new Material[textureCount]; for (int t = 0; t < textureCount; t++) { TrackBuildRTexture texture = textures[t]; if (!texture.isSubstance && !texture.isUSer) { string materialPath = string.Format("{0}{1}/{2}.mat", ROOT_FOLDER, track.exportFilename, texture.customName); if (File.Exists(materialPath)) { Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); EditorUtility.CopySerialized(texture.material, mat); AssetDatabase.SaveAssets(); materials[t] = mat; continue; } Material tempMat = Object.Instantiate(texture.material); AssetDatabase.CreateAsset(tempMat, materialPath); materials[t] = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); } else { materials[t] = texture.isUSer ? texture.userMaterial : texture.proceduralMaterial; } } string[] dynNames = { "track", "bumper", "boundary", "bottom", "offroad", "trackCollider" }; string[] colliderNames = { "track collider", "wall collider", "offroad collider", "bumper collider" }; for (int c = 0; c < numberOfCurves; c++) { TrackBuildRPoint curve = trackData[c]; DynamicMesh[] dynMeshes = new DynamicMesh[numberOfDynMeshes]; dynMeshes[0] = curve.dynamicTrackMesh; dynMeshes[1] = curve.dynamicBumperMesh; dynMeshes[2] = curve.dynamicBoundaryMesh; dynMeshes[3] = curve.dynamicBottomMesh; dynMeshes[4] = curve.dynamicOffroadMesh; dynMeshes[5] = curve.dynamicColliderMesh1; //track surface dynMeshes[6] = curve.dynamicColliderMesh2; //walls and roof dynMeshes[7] = curve.dynamicColliderMesh3; //track bottom and offroad dynMeshes[8] = curve.dynamicColliderMesh4; //bumpers int[] textureIndeices = { curve.trackTextureStyleIndex, curve.bumperTextureStyleIndex, curve.boundaryTextureStyleIndex, curve.bottomTextureStyleIndex, curve.offroadTextureStyleIndex, 0 }; PhysicMaterial[] physicMaterials = { trackData.Texture(curve.trackTextureStyleIndex).physicMaterial, trackData.Texture(curve.boundaryTextureStyleIndex).physicMaterial, trackData.Texture(curve.offroadTextureStyleIndex).physicMaterial, trackData.Texture(curve.bumperTextureStyleIndex).physicMaterial }; for (int d = 0; d < numberOfDynMeshes; d++) { int textureIndex = Mathf.Clamp(d, 0, 5); if (EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "Exporting Track Curve " + c + " " + dynNames[textureIndex], 0.15f + exportProgress * (c * numberOfDynMeshes + d))) { EditorUtility.ClearProgressBar(); return; } DynamicMesh exportDynMesh = dynMeshes[d]; // if(track.includeTangents || exportDynMesh.isEmpty) // exportDynMesh.Build();//rebuild with tangents TrackBuildRTexture texture = trackData.Texture(textureIndeices[textureIndex]); exportTexture.name = texture.customName; exportTexture.material = texture.material; exportTexture.generated = false; exportTexture.filepath = texture.filePath; exportMaterials[0] = exportTexture; Material mat = materials[textureIndeices[textureIndex]]; int meshCount = exportDynMesh.meshCount; Mesh[] meshes = exportDynMesh.meshes; for (int i = 0; i < meshCount; i++) { Mesh exportMesh = meshes[i]; MeshUtility.Optimize(exportMesh); string filenameSuffix = trackModelName(dynNames[textureIndex], c, (meshCount > 1) ? i : -1); // "trackCurve" + c + ((meshCount > 1) ? "_" + i.ToString() : ""); if (d > 4) //colliders { filenameSuffix = string.Format("{0}_{1}", filenameSuffix, (d % 5)); } 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 - 4) { 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; MeshRenderer[] renders = newModel.GetComponentsInChildren <MeshRenderer>(); foreach (MeshRenderer rend in renders) { rend.material = mat; } } else { int colliderIndex = d - (numberOfDynMeshes - 4); GameObject colliderObject = new GameObject(colliderNames[colliderIndex]); MeshCollider collider = colliderObject.AddComponent <MeshCollider>(); collider.sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(modelFilePath, typeof(Mesh)); collider.material = physicMaterials[colliderIndex]; 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("Track BuildR Export Error: " + e); EditorUtility.ClearProgressBar(); AssetDatabase.Refresh();//ensure the database is up to date... } Object.DestroyImmediate(baseObject); EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssetsImmediate(); AssetDatabase.Refresh(); }
void OnEnable() { if (target != null) { _trackBuildR = (TrackBuildR)target; _track = _trackBuildR.track; } _stageToolbarTexturesA = new Texture2D[numberOfMenuOptionsA]; _stageToolbarTexturesA[0] = (Texture2D)Resources.Load("GUI/track"); _stageToolbarTexturesA[1] = (Texture2D)Resources.Load("GUI/boundary"); _stageToolbarTexturesA[2] = (Texture2D)Resources.Load("GUI/bumpers"); _stageToolbarTexturesA[3] = (Texture2D)Resources.Load("GUI/textures"); _stageToolbarTexturesA[4] = (Texture2D)Resources.Load("GUI/terrain"); _stageToolbarTexturesB = new Texture2D[numberOfMenuOptionsB]; _stageToolbarTexturesB[0] = (Texture2D)Resources.Load("GUI/stunt"); _stageToolbarTexturesB[1] = (Texture2D)Resources.Load("GUI/diagram"); _stageToolbarTexturesB[2] = (Texture2D)Resources.Load("GUI/options"); _stageToolbarTexturesB[3] = (Texture2D)Resources.Load("GUI/export"); //Preview Camera if (_trackBuildR.trackEditorPreview != null) { DestroyImmediate(_trackBuildR.trackEditorPreview); } if (!EditorApplication.isPlaying && SystemInfo.supportsRenderTextures) { _trackBuildR.trackEditorPreview = new GameObject("Track Preview Cam"); _trackBuildR.trackEditorPreview.hideFlags = HideFlags.HideAndDontSave; _trackBuildR.trackEditorPreview.AddComponent <Camera>(); _trackBuildR.trackEditorPreview.GetComponent <Camera>().fieldOfView = 80; _trackBuildR.trackEditorPreview.GetComponent <Camera>().depth = -99999; //Retreive camera settings from the main camera Camera[] cams = Camera.allCameras; bool sceneHasCamera = cams.Length > 0; Camera sceneCamera = null; Skybox sceneCameraSkybox = null; if (Camera.main) { sceneCamera = Camera.main; } else if (sceneHasCamera) { sceneCamera = cams[0]; } if (sceneCamera != null) { if (sceneCameraSkybox == null) { sceneCameraSkybox = sceneCamera.GetComponent <Skybox>(); } } if (sceneCamera != null) { _trackBuildR.trackEditorPreview.GetComponent <Camera>().backgroundColor = sceneCamera.backgroundColor; if (sceneCameraSkybox != null) { _trackBuildR.trackEditorPreview.AddComponent <Skybox>().material = sceneCameraSkybox.material; } else if (RenderSettings.skybox != null) { _trackBuildR.trackEditorPreview.AddComponent <Skybox>().material = RenderSettings.skybox; } } } }
/// <summary> /// unfinished! /// </summary> /// <param name="track"></param> /// <param name="selectedPoint"></param> public static void AddTwist(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength); Vector3 twistDirection = atPoint.trackDirection; // Vector3 twistMiddle = atPoint.worldPosition; Vector3 twistUp = atPoint.trackUp; Vector3 twistAxis = Vector3.Cross(twistDirection, twistUp); float twistRadius = track.twistRadius; Vector3 twistStartPosition = -twistDirection * (twistDistance * 0.33f); Vector3 twistEndPosition = twistDirection * (twistDistance * 0.33f); // Vector3 twistCentreHeight = twistUp * twistRadius; Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp); Vector3 twistCenter = atPoint.worldPosition + Vector3.up * twistRadius; float controlPointLength = twistRadius / (Mathf.PI); int numberOfPoints = track.twistPoints; float arcPercent = 1.0f / numberOfPoints; TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints+1]; for (int i = 0; i < numberOfPoints; i++) { float pointArcPercent = arcPercent * i; float radA = Mathf.PI * 2 * (pointArcPercent + 0.5f); Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius); float smoothI = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent); Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI)); Vector3 pointPosition = (pointLoopPosition) + lateral; Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, twistAxis).normalized; TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i); newTrackPoint.worldPosition = twistCenter + pointPosition; newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection); newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength); loopPoints[i] = newTrackPoint; } atPoint.worldPosition += twistStartPosition; atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection); atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis; loopPoints[6] = atPoint; // _trackBuildR.pointMode = TrackBuildR.pointModes.transform; for (int i = 0; i < numberOfPoints + 1; i++) { loopPoints[i].extrudeTrack = true; loopPoints[i].extrudeTrackBottom = true; loopPoints[i].extrudeLength = 0.5f; loopPoints[i].RecalculateStoredValues(); } }
/// <summary> /// Deals with modifing the diagram used in track building /// </summary> private static void UpdateDiagram(TrackBuildRTrack _track) { // Texture texture = _track.diagramMaterial.mainTexture; float scaleSize = Vector3.Distance(_track.scalePointB, _track.scalePointA); float diagramScale = _track.scale / scaleSize; _track.diagramGO.transform.localScale *= diagramScale; _track.scalePointA *= diagramScale; _track.scalePointB *= diagramScale; }
public static void ResetTerrain(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float[,] tData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); for(int x = 0; x < terrainWidth; x++) for(int y = 0; y< terrainHeight; y++) tData[x, y] = 1; terrainData.SetHeights(0, 0, tData); terrain.terrainData = terrainData; }
public static void ConformTrack(TrackBuildRTrack track, Terrain terrain) { TerrainData terrainData = terrain.terrainData; int terrainWidth = terrainData.heightmapWidth; int terrainHeight = terrainData.heightmapHeight; float terrainHeightmapY = terrain.terrainData.heightmapScale.y; float terrainY = terrain.transform.position.y / terrainHeightmapY; float conformAccuracy = track.conformAccuracy; float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight); Bounds trackBounds = new Bounds(); int numberOfCurves = track.numberOfCurves; for (int i = 0; i < numberOfCurves; i++) { TrackBuildRPoint curve = track[i]; if (curve.holder == null) continue; Renderer[] rends = curve.holder.GetComponentsInChildren<Renderer>(); foreach (Renderer rend in rends) { trackBounds.Encapsulate(rend.bounds); } } Vector3 trackOffset = track.transform.position - terrain.transform.position; Vector3 trackScale = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z); int realNumberOfPoints = track.realNumberOfPoints; for(int i = 0; i < realNumberOfPoints; i++) { TrackBuildRPoint point = track[i]; Vector3 trackPointPosition = point.position; int pointX = Mathf.RoundToInt(((trackPointPosition.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); int pointY = Mathf.RoundToInt(((trackPointPosition.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); pointX = Mathf.Clamp(pointX, 0, terrainWidth-1); pointY = Mathf.Clamp(pointY, 0, terrainHeight-1); trackPointPosition.y = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy; point.position = trackPointPosition; Vector3 controlPoint = point.forwardControlPoint; pointX = Mathf.RoundToInt(((controlPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth); pointY = Mathf.RoundToInt(((controlPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight); pointX = Mathf.Clamp(pointX, 0, terrainWidth - 1); pointY = Mathf.Clamp(pointY, 0, terrainHeight - 1); controlPoint.y = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy; point.forwardControlPoint = controlPoint; point.isDirty = true; } track.RecalculateCurves(); }
public static void AddJumpTwist(TrackBuildRTrack track, int selectedPoint) { TrackBuildRPoint atPoint = track[selectedPoint]; TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1); // TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1); float trackPartDistance = lastPoint.arcLength + atPoint.arcLength; float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength); // float trackWidth = atPoint.width * 0.5f; Vector3 startCross = atPoint.trackCross; Vector3 jumpDirection = atPoint.trackDirection; Vector3 jumpMiddle = atPoint.worldPosition; Quaternion atPointUpQ = atPoint.trackUpQ; Quaternion trackUpJump = Quaternion.AngleAxis(track.twistAngle, -jumpDirection); Quaternion trackCrossExit = trackUpJump * (atPointUpQ); Quaternion trackCrossEntry = Quaternion.Inverse(trackUpJump) * (atPointUpQ); Vector3 jumpLateral = startCross * track.twistAngle / 33.3f; Vector3 jumpHeight = atPointUpQ * (Vector3.forward * track.jumpHeight); Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f) + jumpHeight - jumpLateral; Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f) + jumpHeight + jumpLateral; lastPoint.extrudeTrack = true; lastPoint.extrudeLength = track.jumpHeight; lastPoint.extrudeCurveEnd = true; lastPoint.extrudeTrackBottom = true; atPoint.Reset(); atPoint.worldPosition = jumpStartPosition; atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight; atPoint.trackUpQ = trackCrossExit; atPoint.render = false; TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1); jumpEnd.worldPosition = jumpEndPosition; jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition - jumpHeight; jumpEnd.trackUpQ = trackCrossEntry; jumpEnd.extrudeTrack = true; jumpEnd.extrudeLength = track.jumpHeight; jumpEnd.extrudeCurveEnd = true; jumpEnd.extrudeTrackBottom = true; atPoint.RecalculateStoredValues(); jumpEnd.RecalculateStoredValues(); }
/// <summary> /// A stub of GUI for selecting the texture for a specific part of the track on a specific curve /// IE. The track texture, the wall texture, etc... /// </summary> /// <param customName="_track"></param> /// <param customName="textureIndex"></param> /// <param customName="label"></param> /// <returns></returns> private static int CurveTextureSelector(TrackBuildRTrack _track, int textureIndex, string label) { TrackBuildRTexture[] textures = _track.GetTexturesArray(); int numberOfTextures = textures.Length; string[] textureNames = new string[numberOfTextures]; for (int t = 0; t < numberOfTextures; t++) textureNames[t] = textures[t].customName; EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(); EditorGUILayout.LabelField(label); textureIndex = EditorGUILayout.Popup(Mathf.Clamp(textureIndex,0,numberOfTextures-1), textureNames); TrackBuildRTexture tbrTexture = _track.Texture(textureIndex); EditorGUILayout.EndVertical(); GUILayout.Label(tbrTexture.texture, GUILayout.Width(50), GUILayout.Height(50)); EditorGUILayout.EndHorizontal(); return textureIndex; }
public void Init() { track = gameObject.AddComponent<TrackBuildRTrack>(); track.InitTextures(); track.baseTransform = transform; TrackBuildRPoint p0 = gameObject.AddComponent<TrackBuildRPoint>();// ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p1 = gameObject.AddComponent<TrackBuildRPoint>();//ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p2 = gameObject.AddComponent<TrackBuildRPoint>();//ScriptableObject.CreateInstance<TrackBuildRPoint>(); TrackBuildRPoint p3 = gameObject.AddComponent<TrackBuildRPoint>();//ScriptableObject.CreateInstance<TrackBuildRPoint>(); p0.baseTransform = transform; p1.baseTransform = transform; p2.baseTransform = transform; p3.baseTransform = transform; p0.position = new Vector3(-20, 0, -20); p1.position = new Vector3(20, 0, -20); p2.position = new Vector3(20, 0, 20); p3.position = new Vector3(-20, 0, 20); p0.forwardControlPoint = new Vector3(0, 0, -20); p1.forwardControlPoint = new Vector3(40, 0, -20); p2.forwardControlPoint = new Vector3(0, 0, 20); p3.forwardControlPoint = new Vector3(-40, 0, 20); p0.leftForwardControlPoint = new Vector3(-15, 0, -20); p1.leftForwardControlPoint = new Vector3(25, 0, -20); p2.leftForwardControlPoint = new Vector3(5, 0, 20); p3.leftForwardControlPoint = new Vector3(-35, 0, 20); p0.rightForwardControlPoint = new Vector3(15, 0, -20); p1.rightForwardControlPoint = new Vector3(55, 0, -20); p2.rightForwardControlPoint = new Vector3(-5, 0, 20); p3.rightForwardControlPoint = new Vector3(-45, 0, 20); track.AddPoint(p0); track.AddPoint(p1); track.AddPoint(p2); track.AddPoint(p3); generator = gameObject.AddComponent<TrackBuildRGenerator>(); ForceFullRecalculation(); track.diagramMesh = new Mesh(); track.diagramMesh.vertices = new [] { new Vector3(-1, 0, -1), new Vector3(1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, 1)}; track.diagramMesh.uv = new [] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0,1), new Vector2(1,1)}; track.diagramMesh.triangles = new []{1,0,2,1,2,3}; track.diagramGO = new GameObject("Diagram"); track.diagramGO.transform.parent = transform; track.diagramGO.transform.localPosition = Vector3.zero; track.diagramGO.AddComponent<MeshFilter>().mesh = track.diagramMesh; track.diagramMaterial = new Material(Shader.Find("Unlit/Texture")); track.diagramGO.AddComponent<MeshRenderer>().material = track.diagramMaterial; track.diagramGO.AddComponent<MeshCollider>().sharedMesh = track.diagramMesh; }