Пример #1
0
        void AddSolidLaneLine(
            NativeArray <RigidTransform> samples,
            float xOffset,
            RoadMarking marking,
            DynamicBuffer <CombinedVertex> vertexBuffer,
            DynamicBuffer <Triangle> triangleBuffer,
            DynamicBuffer <SubMesh> subMeshBuffer)
        {
            var newSubMesh        = new SubMesh();
            var markingWidth      = marking.Width / 2;
            var leftOffsetSpline  = SplineUtility.OffsetSpline(samples, new float3(-markingWidth + xOffset, 0f, 0f), Allocator.Temp);
            var rightOffsetSpline = SplineUtility.OffsetSpline(samples, new float3(markingWidth + xOffset, 0f, 0f), Allocator.Temp);

            newSubMesh.VertexStartIndex = vertexBuffer.Length;
            newSubMesh.VertexCount      = samples.Length * 2;
            vertexBuffer.ResizeUninitialized(vertexBuffer.Length + samples.Length * 2);

            var upVector = new float3(0f, 1f, 0f);

            for (int i = 0, j = newSubMesh.VertexStartIndex; i < samples.Length; i++)
            {
                var leftPoint = leftOffsetSpline[i];
                vertexBuffer[j++] = new CombinedVertex
                {
                    Vertex = leftPoint.pos,
                    Normal = math.mul(leftPoint.rot, upVector),
                    Uv     = leftPoint.pos.xz
                };
                var rightPoint = rightOffsetSpline[i];
                vertexBuffer[j++] = new CombinedVertex
                {
                    Vertex = rightPoint.pos,
                    Normal = math.mul(rightPoint.rot, upVector),
                    Uv     = rightPoint.pos.xz
                };
            }
            leftOffsetSpline.Dispose();
            rightOffsetSpline.Dispose();

            newSubMesh.TriangleStartIndex = triangleBuffer.Length;
            newSubMesh.TriangleCount      = (samples.Length - 1) * 6;
            triangleBuffer.ResizeUninitialized(triangleBuffer.Length + newSubMesh.TriangleCount);
            for (int i = 0, j = newSubMesh.TriangleStartIndex; i < newSubMesh.VertexCount - 2; i += 2)
            {
                triangleBuffer[j++] = i;
                triangleBuffer[j++] = i + 3;
                triangleBuffer[j++] = i + 1;

                triangleBuffer[j++] = i;
                triangleBuffer[j++] = i + 2;
                triangleBuffer[j++] = i + 3;
            }

            newSubMesh.Material = marking.Material;
            subMeshBuffer.Add(newSubMesh);
        }
Пример #2
0
        /// <summary>
        /// Generates a simplified triangulation for road surfaces that do not have dashed road markings
        /// </summary>
        /// <param name="index"></param>
        void SimpleLoft(int index)
        {
            var surfaceEntity = SurfaceEntities[index];
            var surface       = Surfaces[surfaceEntity];
            var profile       = Profiles[surface.Profile];

            var loftPath             = LoftPathBuffers[profile.Road].Reinterpret <RigidTransform>();
            var lateralProfileBuffer = ProfileSampleBuffers[surface.Profile]
                                       .Reinterpret <float2>().AsNativeArray()
                                       .GetSubArray(surface.StartIndex, surface.SampleCount);
            var lateralProfile = new NativeArray <float2>(lateralProfileBuffer.Length, Allocator.Temp);

            lateralProfile.CopyFrom(lateralProfileBuffer);

            if (surface.LeftLaneMarking != Entity.Null)
            {
                var markingWidth = RoadMarkings[surface.LeftLaneMarking].Width / 2f;
                lateralProfile[0] += new float2(markingWidth, 0f);
            }
            if (surface.RightLaneMarking != Entity.Null)
            {
                var markingWidth = RoadMarkings[surface.RightLaneMarking].Width / 2f;
                lateralProfile[lateralProfile.Length - 1] -= new float2(markingWidth, 0f);
            }

            var numVertices = loftPath.Length * lateralProfile.Length;
            var vertices    = new NativeArray <float3>(numVertices, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            for (var i = 0; i < loftPath.Length; i++)
            {
                for (var j = 0; j < lateralProfile.Length; j++)
                {
                    vertices[i * lateralProfile.Length + j] = math.transform(
                        loftPath[i],
                        Utilities.GeometryUtility.SwizzleXY0(lateralProfile[j]));
                }
            }

            // Create normals for lateral profile
            var lateralProfileNormals = new NativeArray <float3>(lateralProfile.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            {
                var v1 = Utilities.GeometryUtility.SwizzleXY0(math.normalize(lateralProfile[1] - lateralProfile[0]));
                v1 = new float3(-v1.y, v1.x, 0f);
                lateralProfileNormals[0] = v1;

                var v2 = v1;
                for (var j = 1; j < lateralProfile.Length - 1; j++)
                {
                    v2 = Utilities.GeometryUtility.SwizzleXY0(math.normalize(lateralProfile[j + 1] - lateralProfile[j]));
                    v2 = new float3(-v2.y, v2.x, 0f);

                    lateralProfileNormals[j] = math.normalize(v1 + v2);
                    v1 = v2;
                }

                lateralProfileNormals[lateralProfile.Length - 1] = v2;
            }

            var normals = new NativeArray <float3>(numVertices, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            for (var i = 0; i < loftPath.Length; i++)
            {
                for (var j = 0; j < lateralProfile.Length; j++)
                {
                    normals[i * lateralProfile.Length + j] = math.rotate(loftPath[i], lateralProfileNormals[j]);
                }
            }

            var uvs = new NativeArray <float2>(numVertices, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            if (surface.TexStrategy == TextureCoordinateStrategy.WorldSpace)
            {
                for (var i = 0; i < uvs.Length; i++)
                {
                    uvs[i] = vertices[i].xz;
                }
            }
            else
            {
                var us = new NativeArray <float>(lateralProfile.Length, Allocator.Temp)
                {
                    [0] = 0f
                };
                for (var i = 1; i < us.Length; i++)
                {
                    us[i] = math.distance(lateralProfile[i], lateralProfile[i - 1]) + us[i - 1];
                }

                var vs = new NativeArray <float>(loftPath.Length, Allocator.Temp)
                {
                    [0] = 0f
                };
                for (var i = 1; i < vs.Length; i++)
                {
                    vs[i] = math.distance(loftPath[i].pos, loftPath[i - 1].pos) + vs[i - 1];
                }

                for (var i = 0; i < loftPath.Length; i++)
                {
                    for (var j = 0; j < lateralProfile.Length; j++)
                    {
                        uvs[i * lateralProfile.Length + j] = new float2(us[j], vs[i]);
                    }
                }
            }

            var newSubMesh = new SubMesh {
                Material = surface.Material
            };
            var combinedVertexBuffer = CombinedVertexBuffers[surfaceEntity];

            newSubMesh.VertexStartIndex = combinedVertexBuffer.Length;
            newSubMesh.VertexCount      = vertices.Length;
            combinedVertexBuffer.ResizeUninitialized(newSubMesh.VertexStartIndex + newSubMesh.VertexCount);
            for (int i = 0, j = newSubMesh.VertexStartIndex; i < vertices.Length; i++, j++)
            {
                combinedVertexBuffer[j] = new CombinedVertex
                {
                    Vertex = vertices[i],
                    Normal = normals[i],
                    Uv     = uvs[i]
                };
            }

            vertices.Dispose();
            normals.Dispose();
            uvs.Dispose();

            var triangleBuffer = TriangleBuffers[surfaceEntity].Reinterpret <int>();

            newSubMesh.TriangleStartIndex = triangleBuffer.Length;
            var numTriangles = (loftPath.Length - 1) * (lateralProfile.Length - 1) * 6;

            newSubMesh.TriangleCount = numTriangles;
            triangleBuffer.ResizeUninitialized(newSubMesh.TriangleStartIndex + newSubMesh.TriangleCount);
            for (int i = 1, j = newSubMesh.TriangleStartIndex; i < loftPath.Length; i++)
            {
                var prevOffset = (i - 1) * lateralProfile.Length;
                var nextOffset = i * lateralProfile.Length;

                for (var k = 1; k < lateralProfile.Length; k++)
                {
                    triangleBuffer[j++] = prevOffset + k;
                    triangleBuffer[j++] = prevOffset + k - 1;
                    triangleBuffer[j++] = nextOffset + k - 1;

                    triangleBuffer[j++] = nextOffset + k - 1;
                    triangleBuffer[j++] = nextOffset + k;
                    triangleBuffer[j++] = prevOffset + k;
                }
            }

            lateralProfile.Dispose();
            SubMeshBuffers[surfaceEntity].Add(newSubMesh);
        }
Пример #3
0
        /// <summary>
        /// Triangulates a road surface bordered on at least one side by dashed road markings
        /// </summary>
        /// <param name="index"></param>
        void LoftWithDashedRoadMarking(int index)
        {
            var surfaceEntity = SurfaceEntities[index];
            var surface       = Surfaces[surfaceEntity];
            var profile       = Profiles[surface.Profile];

            var lateralProfileBuffer = ProfileSampleBuffers[surface.Profile]
                                       .Reinterpret <float2>().AsNativeArray()
                                       .GetSubArray(surface.StartIndex, surface.SampleCount);
            var leftLateralPoint  = new float3(lateralProfileBuffer[0].x, 0f, 0f);
            var rightLateralPoint = new float3(lateralProfileBuffer[lateralProfileBuffer.Length - 1].x, 0f, 0f);

            var loftPath = LoftPathBuffers[profile.Road].Reinterpret <RigidTransform>().AsNativeArray();
            NativeArray <RigidTransform> leftSamples, rightSamples;
            NativeArray <DashPoint>      leftDashPoints, rightDashPoints;

            if (surface.LeftLaneMarking != Entity.Null &&
                !Utilities.GeometryUtility.ApproximatelyEqual(RoadMarkings[surface.LeftLaneMarking].SeparationDistance, 0f))
            {
                var leftMarkingWidth = RoadMarkings[surface.LeftLaneMarking].Width;
                leftLateralPoint.x += leftMarkingWidth / 2f;
                var roadMarkingSamples = RoadMarkingSampleBuffers[surface.LeftLaneMarking]
                                         .Reinterpret <RigidTransform>().AsNativeArray();
                leftSamples    = Utilities.SplineUtility.OffsetSpline(roadMarkingSamples, leftLateralPoint, Allocator.Temp);
                leftDashPoints = new NativeArray <DashPoint>(DashPointBuffers[surface.LeftLaneMarking].AsNativeArray(), Allocator.Temp);
            }
            else
            {
                if (surface.LeftLaneMarking != Entity.Null)
                {
                    leftLateralPoint.x += RoadMarkings[surface.LeftLaneMarking].Width / 2f;
                }
                leftSamples    = Utilities.SplineUtility.OffsetSpline(loftPath, leftLateralPoint, Allocator.Temp);
                leftDashPoints = new NativeArray <DashPoint>(leftSamples.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                for (var i = 0; i < leftDashPoints.Length; i++)
                {
                    leftDashPoints[i] = new DashPoint {
                        Distance = i
                    };
                }
            }

            if (surface.RightLaneMarking != Entity.Null &&
                !Utilities.GeometryUtility.ApproximatelyEqual(RoadMarkings[surface.RightLaneMarking].SeparationDistance, 0f))
            {
                var rightMarkingWidth = RoadMarkings[surface.RightLaneMarking].Width;
                rightLateralPoint.x -= rightMarkingWidth / 2f;
                var roadMarkingSamples = RoadMarkingSampleBuffers[surface.RightLaneMarking]
                                         .Reinterpret <RigidTransform>().AsNativeArray();
                rightSamples    = Utilities.SplineUtility.OffsetSpline(roadMarkingSamples, rightLateralPoint, Allocator.Temp);
                rightDashPoints = new NativeArray <DashPoint>(DashPointBuffers[surface.RightLaneMarking].AsNativeArray(), Allocator.Temp);
            }
            else
            {
                if (surface.RightLaneMarking != Entity.Null)
                {
                    rightLateralPoint.x -= RoadMarkings[surface.RightLaneMarking].Width / 2f;
                }
                rightSamples    = Utilities.SplineUtility.OffsetSpline(loftPath, rightLateralPoint, Allocator.Temp);
                rightDashPoints = new NativeArray <DashPoint>(rightSamples.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                for (var i = 0; i < rightDashPoints.Length; i++)
                {
                    rightDashPoints[i] = new DashPoint {
                        Distance = i
                    };
                }
            }

            var vertexBuffer = CombinedVertexBuffers[surfaceEntity];
            var numVertices  = leftSamples.Length + rightSamples.Length;

            vertexBuffer.ResizeUninitialized(numVertices);
            var vertexArray = vertexBuffer.AsNativeArray();

            for (var i = 0; i < leftSamples.Length; i++)
            {
                vertexArray[i] = new CombinedVertex
                {
                    Vertex = leftSamples[i].pos,
                    Normal = math.mul(leftSamples[i].rot, new float3(0f, 1f, 0f)),
                    Uv     = leftSamples[i].pos.xz
                };
            }
            for (int i = 0, j = leftSamples.Length; i < rightSamples.Length; i++, j++)
            {
                vertexArray[j] = new CombinedVertex
                {
                    Vertex = rightSamples[i].pos,
                    Normal = math.mul(rightSamples[i].rot, new float3(0f, 1f, 0f)),
                    Uv     = rightSamples[i].pos.xz
                };
            }

            var triangleBuffer = TriangleBuffers[surfaceEntity].Reinterpret <int>();

            triangleBuffer.ResizeUninitialized(3 * (numVertices - 2));
            var triangleArray = triangleBuffer.AsNativeArray();

            var numLeftSamples = leftSamples.Length;

            for (int i = 1, leftStartIdx = 0, rightStartIdx = 0, triangleIdx = 0; i < loftPath.Length; i++)
            {
                var nextLeftIdx  = leftStartIdx + 1;
                var nextRightIdx = rightStartIdx + 1;
                while (!Utilities.GeometryUtility.ApproximatelyEqual(leftDashPoints[nextLeftIdx].Distance, i))
                {
                    nextLeftIdx++;
                }
                while (!Utilities.GeometryUtility.ApproximatelyEqual(rightDashPoints[nextRightIdx].Distance, i))
                {
                    nextRightIdx++;
                }

                for (var j = leftStartIdx; j < nextLeftIdx; j++)
                {
                    triangleArray[triangleIdx++] = rightStartIdx + numLeftSamples;
                    triangleArray[triangleIdx++] = j;
                    triangleArray[triangleIdx++] = j + 1;
                }

                for (var j = rightStartIdx; j < nextRightIdx; j++)
                {
                    triangleArray[triangleIdx++] = nextLeftIdx;
                    triangleArray[triangleIdx++] = numLeftSamples + j + 1;
                    triangleArray[triangleIdx++] = numLeftSamples + j;
                }

                leftStartIdx  = nextLeftIdx;
                rightStartIdx = nextRightIdx;
            }

            var subMeshBuffer = SubMeshBuffers[surfaceEntity];

            subMeshBuffer.Add(new SubMesh
            {
                Material           = RoadMaterial.RoadSurface,
                VertexStartIndex   = 0,
                VertexCount        = vertexArray.Length,
                TriangleStartIndex = 0,
                TriangleCount      = triangleArray.Length
            });

            leftSamples.Dispose();
            leftDashPoints.Dispose();
            rightSamples.Dispose();
            rightDashPoints.Dispose();
        }