Esempio n. 1
0
    public SplineMesh.CurveSample ClosestTrackSample(SplineMesh.Spline track)
    {
        int segmentA = raceController.GetTrackSegment(CarInfo?.name);
        int segmentB = -1;

        if (segmentA < 0)
        {
            segmentA = 0;
            segmentB = raceController.GetNumSegments();
        }
        else
        {
            segmentB = raceController.NextSegment(segmentA);
        }

        float begin = Math.Max(0, raceController.TrackDistanceAtSegment(segmentA));
        float end   = Math.Max(0, raceController.TrackDistanceAtSegment(segmentB));

        var   closest         = track.GetSampleAtDistance(begin);
        float closestDistance = float.MaxValue;

        for (float i = begin; i < end; i += 0.05f)
        {
            var curveSample = track.GetSampleAtDistance(i);
            var d           = (gameObject.transform.position - 0.048f * Vector3.up - curveSample.location);
            d.y *= 10;
            var distance = d.magnitude;
            if (distance < closestDistance)
            {
                closestDistance = distance;
                closest         = curveSample;
            }
        }
        return(closest);
    }
Esempio n. 2
0
 Vector3 GetPosition(float aLength)
 {
     if (line.useWorldSpace)
     {
         return(transform.TransformPoint(spline.GetSampleAtDistance(aLength).location));
     }
     else
     {
         return(spline.GetSampleAtDistance(aLength).location);
     }
 }
Esempio n. 3
0
        private void FillOnce()
        {
            sampleCache.Clear();
            var bentVertices = new List <MeshVertex>(source.Vertices.Count);

            // for each mesh vertex, we found its projection on the curve
            foreach (var vert in source.Vertices)
            {
                float       distance = vert.position.x - source.MinX;
                CurveSample sample;
                if (!sampleCache.TryGetValue(distance, out sample))
                {
                    if (!useSpline)
                    {
                        if (distance > curve.Length)
                        {
                            distance = curve.Length;
                        }
                        sample = curve.GetSampleAtDistance(distance);
                    }
                    else
                    {
                        float distOnSpline = intervalStart + distance;
                        if (distOnSpline > spline.Length)
                        {
                            if (spline.IsLoop)
                            {
                                while (distOnSpline > spline.Length)
                                {
                                    distOnSpline -= spline.Length;
                                }
                            }
                            else
                            {
                                distOnSpline = spline.Length;
                            }
                        }
                        sample = spline.GetSampleAtDistance(distOnSpline);
                    }
                    sampleCache[distance] = sample;
                }

                bentVertices.Add(sample.GetBent(vert));
            }

            MeshUtility.Update(result,
                               source.Mesh,
                               source.Triangles,
                               bentVertices.Select(b => b.position),
                               bentVertices.Select(b => b.normal));
        }
Esempio n. 4
0
        public void Sow()
        {
            UOUtility.DestroyChildren(generated);

            UnityEngine.Random.InitState(randomSeed);
            if (spacing + spacingRange <= 0 ||
                prefab == null)
            {
                return;
            }

            float distance = 0;

            while (distance <= spline.Length)
            {
                CurveSample sample = spline.GetSampleAtDistance(distance);

                GameObject go;
                if (Application.isPlaying)
                {
                    go = Instantiate(prefab, generated.transform);
                }
                else
                {
                    go = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab((UnityEngine.Object)prefab);
                    go.transform.parent = generated.transform;
                }
                go.transform.localRotation = Quaternion.identity;
                go.transform.localPosition = Vector3.zero;
                go.transform.localScale    = Vector3.one;

                // move along spline, according to spacing + random
                go.transform.localPosition = sample.location;
                // apply scale + random
                float rangedScale = scale + UnityEngine.Random.Range(0, scaleRange);
                go.transform.localScale = new Vector3(rangedScale, rangedScale, rangedScale);
                // rotate with random yaw
                if (isRandomYaw)
                {
                    go.transform.Rotate(0, 0, UnityEngine.Random.Range(-180, 180));
                }
                else
                {
                    go.transform.rotation = sample.Rotation;
                }
                // move orthogonaly to the spline, according to offset + random
                Vector3 binormal = sample.tangent;
                binormal = Quaternion.LookRotation(Vector3.right, Vector3.up) * binormal;
                var localOffset = offset + UnityEngine.Random.Range(0, offsetRange * Math.Sign(offset));
                localOffset           *= sample.scale.x;
                binormal              *= localOffset;
                go.transform.position += binormal;

                distance += spacing + UnityEngine.Random.Range(0, spacingRange);
            }
        }
Esempio n. 5
0
        public void Sow()
        {
            UOUtility.DestroyChildren(generated);

            UnityEngine.Random.InitState(randomSeed);
            if (spacing + spacingRange <= 0 ||
                prefab == null)
            {
                return;
            }

            float distance = 0;

            while (distance <= spline.Length)
            {
                CurveSample sample = spline.GetSampleAtDistance(distance);
                if (heightSync)
                {
                    var        sampleLocationWS = spline.transform.TransformPoint(sample.location);
                    RaycastHit hitInfo;
                    if (Physics.Raycast(sampleLocationWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask))
                    {
                        var newSampleLocation = spline.transform.InverseTransformPoint(hitInfo.point);
                        var newSampleUp       = heightNormalSync ? spline.transform.InverseTransformDirection(hitInfo.normal) : sample.up;
                        sample = new CurveSample(newSampleLocation, sample.tangent, newSampleUp, sample.scale, sample.roll, sample.distanceInCurve, sample.timeInCurve, sample.curve);
                    }
                }

                GameObject go;
                go = Instantiate(prefab, generated.transform);
                go.transform.localRotation = Quaternion.identity;
                go.transform.localPosition = Vector3.zero;
                go.transform.localScale    = Vector3.one;

                go.isStatic = false == updateInPlayMode;
                go.layer    = gameObject.layer;
                foreach (var child in go.transform.Cast <Transform>())
                {
                    child.gameObject.layer = go.layer;
                }

                // move along spline, according to spacing + random
                go.transform.localPosition = sample.location;
                // apply scale + random
                float rangedScale = scale + UnityEngine.Random.Range(0, scaleRange);
                go.transform.localScale = new Vector3(rangedScale, rangedScale, rangedScale);
                // rotate with random yaw
                if (isRandomYaw)
                {
                    go.transform.Rotate(0, 0, UnityEngine.Random.Range(-180, 180));
                }
                else
                {
                    go.transform.rotation = sample.Rotation;
                }
                // move orthogonaly to the spline, according to offset + random
                var binormal          = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.right).normalized;
                var localWidthOffset  = widthOffset + UnityEngine.Random.Range(0, widthOffsetRange * Math.Sign(widthOffset));
                var localHeightOffset = heightOffset + UnityEngine.Random.Range(0, heightOffsetRange * Math.Sign(heightOffset));

                localWidthOffset      *= sample.scale.x;
                binormal              *= localWidthOffset;
                go.transform.position += binormal + sample.up * localHeightOffset;

                distance += spacing + UnityEngine.Random.Range(0, spacingRange);
            }
        }
Esempio n. 6
0
        public void CreateMeshes()
        {
            if (null == spline || null == meshInfos || 0 == meshInfos.Length)
            {
                return;
            }

            UpdateSourceMeshes();
            UpdateDecisionParts();

            string generatedName     = "generated by " + GetType().Name;
            var    generatedTranform = transform.Find(generatedName);

            generated          = generatedTranform != null ? generatedTranform.gameObject : UOUtility.Create(generatedName, gameObject);
            generated.isStatic = false == updateInPlayMode;
            generated.layer    = gameObject.layer;

            var generatedChildren = generated.transform.Cast <Transform>().ToList();

            foreach (var child in generatedChildren)
            {
                if (null == child)
                {
                    continue;
                }

                var meshCollider = child.GetComponent <MeshCollider>();
                if (meshCollider)
                {
                    meshCollider.enabled = false;
                }
            }

            var meshChunkDict = new Dictionary <Material, List <MeshChunk> >();
            var sampleCache   = new Dictionary <float, CurveSample>();

            float offset = 0;

            for (int i = 0; i < decisionParts.Count; ++i)
            {
                int index = decisionParts[i];

                if (false == meshChunkDict.ContainsKey(meshInfos[index].material))
                {
                    meshChunkDict.Add(meshInfos[index].material, new List <MeshChunk>());
                }

                var meshChunkList = meshChunkDict[meshInfos[index].material];

                int vertexCount = meshInfos[index].mesh.vertices.Length;

                bool isReachedMaxVertices = 0 < meshChunkList.Count && PerChunkMaxVertices < (meshChunkList.Last().bentVertices.Count + vertexCount);
                bool isReachedMaxLength   = 0 < meshChunkList.Count && PerChunkMaxLength < meshChunkList.Last().length;
                if (0 == meshChunkList.Count || isReachedMaxVertices || isReachedMaxLength)
                {
                    meshChunkList.Add(new MeshChunk()
                    {
                        bentVertices = new List <MeshVertex>(vertexCount),
                        triangles    = new List <int>(vertexCount / 3),
                        uv           = new List <Vector2> [8],
                        length       = 0
                    });
                }

                var meshChunk = meshChunkList.Last();

                ref SourceMesh sourceMesh = ref sourceMeshes[index];

                meshChunk.triangles.AddRange(sourceMesh.Triangles.Select(idx => idx + meshChunk.bentVertices.Count));
                List <Vector2> UV = new List <Vector2>();
                for (int channel = 0; channel < 8; ++channel)
                {
                    UV.Clear();
                    sourceMesh.Mesh.GetUVs(channel, UV);
                    if (0 < UV.Count)
                    {
                        if (null == meshChunk.uv[channel])
                        {
                            meshChunk.uv[channel] = new List <Vector2>();
                        }
                        int fillCount = Mathf.Max(0, (meshChunk.bentVertices.Count - UV.Count) - meshChunk.uv[channel].Count);
                        if (0 < fillCount)
                        {
                            meshChunk.uv[channel].AddRange(Enumerable.Repeat(Vector2.zero, fillCount));
                        }
                        meshChunk.uv[channel].AddRange(UV);
                    }
                }

                foreach (var vertex in sourceMesh.Vertices)
                {
                    var vert = new MeshVertex(vertex.position, vertex.normal, vertex.uv);

                    vert.position.x *= partsScale;

                    float distance = vert.position.x - sourceMesh.MinX * partsScale + offset;

                    distance = Mathf.Clamp(distance, 0, spline.Length);

                    CurveSample sample;
                    if (false == sampleCache.TryGetValue(distance, out sample))
                    {
                        sample = spline.GetSampleAtDistance(distance);
                        if (heightSync)
                        {
                            var        sampleLocationWS = spline.transform.TransformPoint(sample.location);
                            RaycastHit hitInfo;
                            if (Physics.Raycast(sampleLocationWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask))
                            {
                                var newSampleLocation = spline.transform.InverseTransformPoint(hitInfo.point);
                                var newSampleUp       = heightNormalSync ? spline.transform.InverseTransformDirection(hitInfo.normal) : sample.up;
                                sample = new CurveSample(newSampleLocation, sample.tangent, newSampleUp, sample.scale, sample.roll, sample.distanceInCurve, sample.timeInCurve, sample.curve);
                            }
                        }

                        sampleCache.Add(distance, sample);
                    }

                    MeshVertex bentVertex = sample.GetBent(vert);
                    meshChunk.bentVertices.Add(bentVertex);
                }

                offset           += sourceMeshes[index].Length * partsScale;
                meshChunk.length += sourceMeshes[index].Length * partsScale;
            }
Esempio n. 7
0
        private void CreateMeshes()
        {
            if (null == spline)
            {
                return;
            }

            string generatedName     = "generated by " + GetType().Name;
            var    generatedTranform = transform.Find(generatedName);

            generated          = generatedTranform != null ? generatedTranform.gameObject : UOUtility.Create(generatedName, gameObject);
            generated.isStatic = false == updateInPlayMode;
            generated.layer    = gameObject.layer;

            var generatedChildren = generated.transform.Cast <Transform>().ToList();

            foreach (var child in generatedChildren)
            {
                if (null == child)
                {
                    continue;
                }

                var meshCollider = child.GetComponent <MeshCollider>();
                if (meshCollider)
                {
                    meshCollider.enabled = false;
                }
            }

            List <MeshVertex> sourceVertices = new List <MeshVertex>(2 + Mathf.Max(0, slice - 1));
            float             x_start        = offset - width / 2;
            float             x_end          = offset + width / 2;

            sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x_start), Vector3.up, new Vector2(+textureOffsetScale.x, 0)));
            for (int step = 1; step < slice; ++step)
            {
                float t = (float)step / (float)slice;
                float x = Mathf.Lerp(x_start, x_end, t);
                sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x), Vector3.up, new Vector2(t / textureOffsetScale.z + textureOffsetScale.x, 0)));
            }
            sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x_end), Vector3.up, new Vector2(1 / textureOffsetScale.z + textureOffsetScale.x, 0)));

            if (Mathf.Approximately(sampleSpacing, 0) || sampleSpacing <= 0)
            {
                Debug.LogError("Not enough sampleSpcaing. (must be greater than zero)");
                return;
            }

            int lineCount = 0;
            List <MeshVertex> bentVertices = new List <MeshVertex>();

            for (float d = 0.0f; d <= spline.Length; d += sampleSpacing)
            {
                var sample = spline.GetSampleAtDistance(d);

                if (heightSync)
                {
                    var        sampleLocationWS = spline.transform.TransformPoint(sample.location);
                    RaycastHit hitInfo;
                    if (Physics.Raycast(sampleLocationWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask))
                    {
                        var newSampleLocation = spline.transform.InverseTransformPoint(hitInfo.point);
                        sample = new CurveSample(newSampleLocation, sample.tangent, sample.up, sample.scale, sample.roll, sample.distanceInCurve, sample.timeInCurve, sample.curve);
                    }
                }

                for (int i = 0; i < sourceVertices.Count; ++i)
                {
                    var bentVertex = sample.GetBent(sourceVertices[i]);

                    bentVertex.normal = sample.up;

                    if (heightSync)
                    {
                        var        bentWS = spline.transform.TransformPoint(bentVertex.position);
                        RaycastHit hitInfo;
                        if (Physics.Raycast(bentWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask))
                        {
                            bentVertex.position = spline.transform.InverseTransformPoint(hitInfo.point);
                            if (heightNormalSync)
                            {
                                bentVertex.normal = spline.transform.InverseTransformDirection(hitInfo.normal);
                            }
                        }
                    }

                    bentVertex.uv.y = (d / width) / textureOffsetScale.w + textureOffsetScale.y;

                    bentVertices.Add(bentVertex);
                }

                ++lineCount;
            }

            if (1 >= lineCount)
            {
                Debug.LogError("Not enough line length");
                return;
            }

            List <Transform> newGeneratedTransform = new List <Transform>();

            int        baseIndex         = 0;
            int        lineVerticesCount = 2 + Mathf.Max(0, slice - 1);
            List <int> triangles         = new List <int>((lineVerticesCount - 1) * (lineCount - 1) * 2);

            for (int i = 0; i < lineCount - 1; ++i)
            {
                int nextBaseIndex = baseIndex + lineVerticesCount;
                for (int v = 0; v < lineVerticesCount - 1; ++v)
                {
                    int[] vertices = new int[] {
                        baseIndex + v, baseIndex + v + 1,
                        nextBaseIndex + v, nextBaseIndex + v + 1
                    };
                    triangles.Add(vertices[0]);
                    triangles.Add(vertices[1]);
                    triangles.Add(vertices[2]);
                    triangles.Add(vertices[2]);
                    triangles.Add(vertices[1]);
                    triangles.Add(vertices[3]);
                }

                bool isOverVertices      = nextBaseIndex + lineVerticesCount > PerSegmentMaxVertices;
                bool isEndLine           = (i == lineCount - 2);
                bool needGenerateSegment = isOverVertices || isEndLine;

                if (needGenerateSegment)
                {
                    string    segmentName      = $"{name}-{material.name}-{newGeneratedTransform.Count + 1}";
                    Transform segmentTransform = generated.transform.Find(segmentName);
                    if (null == segmentTransform)
                    {
                        var go = UOUtility.Create(segmentName,
                                                  generated,
                                                  typeof(MeshFilter),
                                                  typeof(MeshRenderer),
                                                  typeof(MeshCollider));
                        segmentTransform = go.transform;
                    }
                    segmentTransform.gameObject.isStatic = generated.isStatic;
                    segmentTransform.gameObject.layer    = generated.layer;

                    newGeneratedTransform.Add(segmentTransform);
                    generatedChildren.Remove(segmentTransform);

                    var meshFilter   = segmentTransform.GetComponent <MeshFilter>();
                    var meshRenderer = segmentTransform.GetComponent <MeshRenderer>();
                    var meshCollider = segmentTransform.GetComponent <MeshCollider>();

                    Mesh mesh = meshFilter.sharedMesh;
                    if (null == mesh || mesh.name != segmentName)
                    {
                        mesh = new Mesh();
                    }
                    else if (mesh.vertexCount != bentVertices.Count)
                    {
                        mesh.Clear();
                    }

                    mesh.name        = segmentName;
                    mesh.hideFlags   = HideFlags.HideInHierarchy;
                    mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt16;

                    var segmentBentVertices = bentVertices.GetRange(0, nextBaseIndex + lineVerticesCount);

                    mesh.SetVertices(segmentBentVertices.Select(b => b.position).ToList());
                    mesh.SetNormals(segmentBentVertices.Select(b => b.normal).ToList());
                    mesh.SetUVs(0, segmentBentVertices.Select(b => b.uv).ToList());
                    mesh.SetTriangles(triangles, 0, false);

                    mesh.RecalculateBounds();
                    mesh.RecalculateTangents();

                    meshFilter.sharedMesh   = mesh;
                    meshRenderer.material   = material;
                    meshCollider.sharedMesh = mesh;

                    meshCollider.enabled = generateCollider;

                    triangles.Clear();
                    bentVertices.RemoveRange(0, nextBaseIndex);

                    nextBaseIndex = 0;
                }

                baseIndex = nextBaseIndex;
            }

            foreach (var deprecatedTransform in generatedChildren)
            {
                if (deprecatedTransform != null)
                {
                    UOUtility.Destroy(deprecatedTransform.gameObject);
                }
            }
        }