├── Textures ├── line_smooth.png ├── line_round_cap.png ├── line_square_cap.png ├── line_round_cap.png.meta ├── line_smooth.png.meta └── line_square_cap.png.meta ├── .Documentation └── images │ ├── line.png │ ├── ss1.png │ └── billboard.gif ├── Scripts ├── Authoring │ ├── LineAuthoring.cs.meta │ └── LineAuthoring.cs ├── Authoring.meta ├── Internal.meta ├── Obsolete.meta ├── Systems.meta ├── Data Structures.meta ├── Internal │ ├── MeshProvider.cs.meta │ └── MeshProvider.cs ├── Data Structures │ ├── LineSegment.cs.meta │ ├── LineStyle.cs.meta │ ├── LineSegment.cs │ └── LineStyle.cs └── Systems │ ├── LineSegmentRegisterSystem.cs.meta │ ├── LineStyleUpdateSystem.cs.meta │ ├── LineSegmentTransformSystem.cs.meta │ ├── LineSegmentWorldBoundsSystem.cs.meta │ ├── LineSegmentWorldBoundsSystem.cs │ ├── LineStyleUpdateSystem.cs │ ├── LineSegmentTransformSystem.cs │ └── LineSegmentRegisterSystem.cs ├── LICENSE.meta ├── CHANGELOG.md.meta ├── README.md.meta ├── package.json.meta ├── Materials.meta ├── Samples.meta ├── Scripts.meta ├── Shaders.meta ├── Textures.meta ├── E7.ECS.LineRenderer.asmdef.meta ├── Samples ├── Entity workflow.meta ├── Entity workflow │ ├── Entity workflow.unity.meta │ ├── EntityWorkflowSpawner.cs.meta │ ├── EntityWorkflowSpawnerSimple.cs.meta │ ├── EntityWorkflowSpawnerSimple.cs │ ├── EntityWorkflowSpawner.cs │ └── Entity workflow.unity ├── GameObject conversion workflow │ ├── subscene.unity.meta │ ├── GameObject conversion workflow.unity.meta │ ├── GameObject conversion workflowSettings.lighting.meta │ ├── GameObject conversion workflowSettings.lighting │ ├── subscene.unity │ └── GameObject conversion workflow.unity └── GameObject conversion workflow.meta ├── Materials ├── [EcsLineRenderer] green line.mat.meta ├── [EcsLineRenderer] white line.mat.meta ├── [EcsLineRenderer] yellow line.mat.meta ├── [EcsLineRenderer] white line.mat ├── [EcsLineRenderer] green line.mat └── [EcsLineRenderer] yellow line.mat ├── Shaders ├── line color.shader.meta └── line color.shader ├── .github └── FUNDING.yml ├── E7.ECS.LineRenderer.asmdef ├── CHANGELOG.md ├── package.json ├── LICENSE └── README.md /Textures/line_smooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/Textures/line_smooth.png -------------------------------------------------------------------------------- /Textures/line_round_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/Textures/line_round_cap.png -------------------------------------------------------------------------------- /.Documentation/images/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/.Documentation/images/line.png -------------------------------------------------------------------------------- /.Documentation/images/ss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/.Documentation/images/ss1.png -------------------------------------------------------------------------------- /Textures/line_square_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/Textures/line_square_cap.png -------------------------------------------------------------------------------- /.Documentation/images/billboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/5argon/ECSLineRenderer/HEAD/.Documentation/images/billboard.gif -------------------------------------------------------------------------------- /Scripts/Authoring/LineAuthoring.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ce30cc957f04b8298732711bc17ad2a 3 | timeCreated: 1578299125 -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b739cd66536d248819f7930450ad96be 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc25f12078426482aaef6dde3fb66dd2 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9dba1d17276a74627b88ba53a6fb0933 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79d40860d90e74a268b64f70a7efc93c 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e07508067cc5ad34da96ab266ae284d3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8863b2fdc54cd47698430b5c04255782 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3cddf2b9a8da2ac4f97fae7c87262042 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7d5a39f71a36f841aac97d75f593d95 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87442d22a071d2543a294ba1422b0989 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /E7.ECS.LineRenderer.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 233527741f2ec47f3aa8bfc24c1bc6e9 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Authoring.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a308dac5fe2ccf64c92e684707cf654b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Internal.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32c8951697ab3f948b4a21b867e19774 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Obsolete.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18c7ef8e355657f4b960ea3c6821e2e3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Systems.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd3766c8d07724ae59e6842540fc8f4e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples/Entity workflow.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4dbe8a21ca70cc1478096625dab23432 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples/Entity workflow/Entity workflow.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db8e22f6722af1a428091d5f623a04a1 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Data Structures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 31a84ce05fe4844d984a51891c73e9cb 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples/GameObject conversion workflow/subscene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0d84db97024d481abb2d5f196688d72 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples/GameObject conversion workflow.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 03c6f30c9d15a2a418e436421565ebd2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples/GameObject conversion workflow/GameObject conversion workflow.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 702181707b64e4c40ada18b37677d99b 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] green line.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9069b8ba7f43a4dffa02cfea63841504 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] white line.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1fbda605d73209b448a1a6fd48459848 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] yellow line.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c5ead89256d6d4e2cb29e3e747ecc99b 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/line color.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f984f03111184a4478867e0ec34b6c09 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples/GameObject conversion workflow/GameObject conversion workflowSettings.lighting.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a07c0ff895d7a87469341ded43459034 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 4890085278179872738 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Internal/MeshProvider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 271b343a58eab924b922f0e3055961c0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Data Structures/LineSegment.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a60b08e616864025a7c694b1e07aaec 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Data Structures/LineStyle.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df5d18951b71f4ed6b1f7d4e47899e97 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Systems/LineSegmentRegisterSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77c2ab762e34a4333b1d6edf80c6cd67 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Systems/LineStyleUpdateSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e4293db282b0f74d8b9e109219cf0a5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples/Entity workflow/EntityWorkflowSpawner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ba0c5c5bd678414b9b4f87e58f7c6e9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Systems/LineSegmentTransformSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e85270158c1e04ec5a69432c0d3225cc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Systems/LineSegmentWorldBoundsSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b939d51ef41182f4e9254b0479486ec5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples/Entity workflow/EntityWorkflowSpawnerSimple.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6534ab66a8004214eb55867bad2f413e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: 5argon 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: 5argon 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: https://assetstore.unity.com/publishers/18007 9 | -------------------------------------------------------------------------------- /E7.ECS.LineRenderer.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "E7.ECS.LineRenderer", 3 | "references": [ 4 | "Unity.Burst", 5 | "Unity.Collections", 6 | "Unity.Entities", 7 | "Unity.Entities.Hybrid", 8 | "Unity.Jobs", 9 | "Unity.Mathematics", 10 | "Unity.Mathematics.Extensions", 11 | "Unity.Rendering.Hybrid", 12 | "Unity.Transforms", 13 | "Unity.Transforms.Hybrid" 14 | ], 15 | "optionalUnityReferences": [], 16 | "includePlatforms": [], 17 | "excludePlatforms": [], 18 | "allowUnsafeCode": false, 19 | "overrideReferences": false, 20 | "precompiledReferences": [], 21 | "autoReferenced": true, 22 | "defineConstraints": [], 23 | "versionDefines": [] 24 | } -------------------------------------------------------------------------------- /Scripts/Internal/MeshProvider.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace E7.ECS.LineRenderer.Internal 4 | { 5 | public static class MeshProvider 6 | { 7 | 8 | public static Mesh lineMesh { get; private set; } 9 | 10 | static MeshProvider () 11 | { 12 | lineMesh = new Mesh(); 13 | lineMesh.hideFlags |= HideFlags.DontSave; 14 | lineMesh.name = "quad 1x1, pivot at bottom center"; 15 | lineMesh.vertices = new Vector3[4]{ new Vector3{ x=-0.5f } , new Vector3{ x=0.5f } , new Vector3{ x=-0.5f , z=1 } , new Vector3{ x=0.5f , z=1 } }; 16 | lineMesh.triangles = new int[6]{ 0 , 2 , 1 , 2 , 3 , 1 }; 17 | lineMesh.normals = new Vector3[4]{ -Vector3.forward , -Vector3.forward , -Vector3.forward , -Vector3.forward }; 18 | lineMesh.uv = new Vector2[4]{ new Vector2{ x=0 , y=0 } , new Vector2{ x=1 , y=0 } , new Vector2{ x=0 , y=1 } , new Vector2{ x=1 , y=1 } }; 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.1.0] - 2021-07-14 8 | 9 | ### Changed 10 | 11 | - Now requires Entities version 0.17.0-preview.42 and Hybrid Renderer version 0.11.0-preview.44. 12 | - Now requires minimum Unity 2020.3 LTS. 13 | - Refactor and new test scene, contributed by [andrew-raphael-lukasik](https://github.com/5argon/ECSLineRenderer/pull/10) 14 | 15 | ### Removed 16 | 17 | - Removed `GameObject` proxy workflow, it is now removed complete from Entities codebase instead of being obsolete. Use Game Object Conversion Workflow instead. 18 | 19 | ## [1.0.0] - 2019-05-29 20 | 21 | Updated for Entities preview.33 and the first version to keep a changelog. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.e7.ecs.line-renderer", 3 | "author": "Sirawat Pitaksarit / 5argon - Exceed7 Experiments", 4 | "displayName": "ECS Line Renderer", 5 | "version": "1.1.0", 6 | "unity": "2020.3", 7 | "description": "ECS approach to render a line.", 8 | "documentationUrl": "https://github.com/5argon/ECSLineRenderer", 9 | "dependencies": { 10 | "com.unity.entities": "0.17.0-preview.42", 11 | "com.unity.rendering.hybrid": "0.11.0-preview.44" 12 | }, 13 | "keywords": [ 14 | "entities", 15 | "hybrid", 16 | "rendering" 17 | ], 18 | "samples": [ 19 | { 20 | "displayName": "GameObject conversion workflow", 21 | "description": "", 22 | "path": "Samples/GameObject conversion workflow" 23 | }, 24 | { 25 | "displayName": "Entity workflow", 26 | "description": "", 27 | "path": "Samples/Entity workflow" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Scripts/Data Structures/LineSegment.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Unity.Entities; 5 | using Unity.Mathematics; 6 | using System; 7 | 8 | namespace E7.ECS.LineRenderer 9 | { 10 | /// 11 | /// This component is not intended to be a fully-fledged line, but rather a part of it. 12 | /// A complete line consists of multiple segments of no-cap lines, 13 | /// joined with "corner segment" then end with "line cap". (No work done on those yet) 14 | /// 15 | [Serializable] 16 | public struct LineSegment : IComponentData 17 | { 18 | public float3 from; 19 | public float3 to; 20 | public float lineWidth; 21 | public override string ToString() => $"{from} -> {to} width {lineWidth}"; 22 | 23 | public LineSegment(float3 from, float3 to, float lineWidth = 0.1f) 24 | { 25 | this.from = from; 26 | this.to = to; 27 | this.lineWidth = lineWidth; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Scripts/Authoring/LineAuthoring.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unity.Entities; 3 | using Unity.Mathematics; 4 | using UnityEngine; 5 | 6 | namespace E7.ECS.LineRenderer 7 | { 8 | /// 9 | /// For use with Game Object Conversion Workflow / Subscene. 10 | /// 11 | /// Generates an Entity with and . 12 | /// Then will pick that up. 13 | /// 14 | public class LineAuthoring : MonoBehaviour, IConvertGameObjectToEntity 15 | { 16 | public LineSegment lineSegment; 17 | public LineStyle lineStyle; 18 | 19 | void OnValidate() 20 | { 21 | lineSegment.lineWidth = math.max(0, lineSegment.lineWidth); 22 | } 23 | 24 | public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) 25 | { 26 | dstManager.AddComponentData(entity, lineSegment); 27 | dstManager.AddSharedComponentData(entity, lineStyle); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Sirawat Pitaksarit (5argon) - Exceed7 Experiments 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Scripts/Data Structures/LineStyle.cs: -------------------------------------------------------------------------------- 1 | using Unity.Entities; 2 | using System; 3 | using UnityEngine; 4 | 5 | namespace E7.ECS.LineRenderer 6 | { 7 | /// 8 | /// This is some properties of the line that could be shared between different lines. 9 | /// When line corners and line caps are supported, this component could also be used with them. 10 | /// 11 | [Serializable] 12 | public struct LineStyle : ISharedComponentData, IEquatable 13 | { 14 | public Material material; 15 | 16 | // /// 17 | // /// WIP : Override billboard camera target. 18 | // /// 19 | // public Camera alignWithCamera; 20 | 21 | // /// 22 | // /// WIP 23 | // /// 24 | // public int endCapVertices; 25 | 26 | // /// 27 | // /// WIP 28 | // /// 29 | // public int cornerVertices; 30 | 31 | public bool Equals(LineStyle other) 32 | => ReferenceEquals(material, other.material); 33 | 34 | public override int GetHashCode() 35 | => ReferenceEquals(material, null) ? material.GetHashCode() : 0; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Scripts/Systems/LineSegmentWorldBoundsSystem.cs: -------------------------------------------------------------------------------- 1 | using Unity.Entities; 2 | using Unity.Jobs; 3 | using Unity.Mathematics; 4 | using Unity.Transforms; 5 | using Unity.Rendering; 6 | 7 | namespace E7.ECS.LineRenderer 8 | { 9 | /// 10 | /// Calculates . 11 | /// NOTE: Start this system when you need but no other system calculates it and you still want to do a culling pass etc. 12 | /// world.GetOrCreateSystem().Update(); 13 | /// 14 | [WorldSystemFilter(0)] 15 | [UpdateInGroup(typeof(InitializationSystemGroup))] 16 | public class LineSegmentWorldRenderBoundsSystem : SystemBase 17 | { 18 | protected override void OnUpdate () 19 | { 20 | Entities 21 | .WithName("WorldRenderBounds_update_job") 22 | .ForEach( ( ref WorldRenderBounds wrb , in RenderBounds bounds , in LineSegment segment ) => 23 | { 24 | float3 lineVec = segment.to - segment.from; 25 | var rot = quaternion.identity; 26 | var pos = segment.from; 27 | var scale = new float3{ x=segment.lineWidth , y=1f , z=math.length(lineVec) }; 28 | wrb.Value = AABB.Transform( float4x4.TRS(pos,rot,scale) , bounds.Value ); 29 | }).ScheduleParallel(); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Scripts/Systems/LineStyleUpdateSystem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Unity.Entities; 3 | using Unity.Mathematics; 4 | using Unity.Collections; 5 | using Unity.Jobs; 6 | using Unity.Rendering; 7 | using Unity.Transforms; 8 | using UnityEngine; 9 | 10 | namespace E7.ECS.LineRenderer 11 | { 12 | /// 13 | /// Forwards changes in component to component. 14 | /// NOTE: System is started 100% manually until it's performace is sorted out. 15 | /// world.GetOrCreateSystem().Update(); 16 | /// 17 | [WorldSystemFilter( 0 )] 18 | [UpdateInGroup(typeof(InitializationSystemGroup))] 19 | public class LineStyleUpdateSystem : SystemBase 20 | { 21 | 22 | EntityQuery _query; 23 | List _styles = new List(10); 24 | 25 | protected override void OnCreate () 26 | { 27 | _query = EntityManager.CreateEntityQuery( 28 | ComponentType.ReadOnly() 29 | , ComponentType.ReadWrite() 30 | ); 31 | } 32 | 33 | protected override void OnUpdate () 34 | { 35 | var command = EntityManager; 36 | 37 | _styles.Clear(); 38 | command.GetAllUniqueSharedComponentData( _styles ); 39 | 40 | var mesh = Internal.MeshProvider.lineMesh; 41 | int numStyles = _styles.Count; 42 | for( int i=0 ; i 24 | { 25 | float3 lineVec = segment.to - segment.from; 26 | var rot = quaternion.LookRotation( math.normalize(lineVec) , math.normalize(cameraPosition-segment.from) ); 27 | var pos = segment.from; 28 | var scale = new float3{ x=segment.lineWidth , y=1f , z=math.length(lineVec) }; 29 | ltr.Value = float4x4.TRS( pos , rot , scale ); 30 | }).ScheduleParallel(); 31 | } 32 | else// orthographic-projection camera 33 | { 34 | quaternion cameraRotation = cameraTransform.rotation; 35 | Entities 36 | .WithName("TRS_orthographic_update_job") 37 | .ForEach( ( ref LocalToWorld ltr , in LineSegment segment ) => 38 | { 39 | float3 lineVec = segment.to - segment.from; 40 | var rot = quaternion.LookRotation( math.normalize(lineVec) , math.mul(cameraRotation,new float3{z=-1}) ); 41 | var pos = segment.from; 42 | var scale = new float3{ x=segment.lineWidth , y=1f , z=math.length(lineVec) }; 43 | ltr.Value = float4x4.TRS( pos , rot , scale ); 44 | }).ScheduleParallel(); 45 | } 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Scripts/Systems/LineSegmentRegisterSystem.cs: -------------------------------------------------------------------------------- 1 | using Unity.Entities; 2 | using Unity.Mathematics; 3 | using Unity.Collections; 4 | using Unity.Jobs; 5 | using Unity.Rendering; 6 | using Unity.Transforms; 7 | using UnityEngine; 8 | 9 | namespace E7.ECS.LineRenderer 10 | { 11 | /// 12 | /// Any new together with 13 | /// get TRS, LTW, and so it is ready for rendering. 14 | /// 15 | [ExecuteAlways] 16 | [UpdateInGroup(typeof(InitializationSystemGroup))] 17 | public class LineSegmentRegisterSystem : SystemBase 18 | { 19 | 20 | protected override void OnUpdate () 21 | { 22 | var mesh = Internal.MeshProvider.lineMesh; 23 | var bounds = mesh.bounds; 24 | AABB aabb = new AABB{ Center=bounds.center , Extents = bounds.extents }; 25 | EntityCommandBuffer ecb = new EntityCommandBuffer( Allocator.Temp ); 26 | 27 | Entities 28 | .WithName("add_components_job") 29 | .WithoutBurst() 30 | .WithNone() 31 | .ForEach( ( in Entity entity , in LineStyle style , in LineSegment segment ) => 32 | { 33 | ecb.AddSharedComponent( entity , new RenderMesh{ 34 | mesh = mesh , 35 | material = style.material 36 | }); 37 | ecb.AddComponent( entity , ComponentType.ReadWrite() ); 38 | ecb.AddComponent( entity , ComponentType.ReadWrite() ); 39 | ecb.SetComponent( entity , new RenderBounds{ 40 | Value = aabb 41 | }); 42 | ecb.AddComponent( entity , ComponentType.ReadWrite() ); 43 | }).Run(); 44 | 45 | ecb.Playback( EntityManager ); 46 | ecb.Dispose(); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Samples/GameObject conversion workflow/GameObject conversion workflowSettings.lighting: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!850595691 &4890085278179872738 4 | LightingSettings: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_Name: GameObject conversion workflowSettings 10 | serializedVersion: 3 11 | m_GIWorkflowMode: 1 12 | m_EnableBakedLightmaps: 0 13 | m_EnableRealtimeLightmaps: 0 14 | m_RealtimeEnvironmentLighting: 1 15 | m_BounceScale: 1 16 | m_AlbedoBoost: 1 17 | m_IndirectOutputScale: 1 18 | m_UsingShadowmask: 1 19 | m_BakeBackend: 0 20 | m_LightmapMaxSize: 1024 21 | m_BakeResolution: 40 22 | m_Padding: 2 23 | m_TextureCompression: 1 24 | m_AO: 0 25 | m_AOMaxDistance: 1 26 | m_CompAOExponent: 1 27 | m_CompAOExponentDirect: 0 28 | m_ExtractAO: 0 29 | m_MixedBakeMode: 2 30 | m_LightmapsBakeMode: 1 31 | m_FilterMode: 1 32 | m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} 33 | m_ExportTrainingData: 0 34 | m_TrainingDataDestination: TrainingData 35 | m_RealtimeResolution: 2 36 | m_ForceWhiteAlbedo: 0 37 | m_ForceUpdates: 0 38 | m_FinalGather: 0 39 | m_FinalGatherRayCount: 256 40 | m_FinalGatherFiltering: 1 41 | m_PVRCulling: 1 42 | m_PVRSampling: 1 43 | m_PVRDirectSampleCount: 32 44 | m_PVRSampleCount: 500 45 | m_PVREnvironmentSampleCount: 500 46 | m_PVREnvironmentReferencePointCount: 2048 47 | m_LightProbeSampleCountMultiplier: 4 48 | m_PVRBounces: 2 49 | m_PVRMinBounces: 2 50 | m_PVREnvironmentMIS: 0 51 | m_PVRFilteringMode: 2 52 | m_PVRDenoiserTypeDirect: 0 53 | m_PVRDenoiserTypeIndirect: 0 54 | m_PVRDenoiserTypeAO: 0 55 | m_PVRFilterTypeDirect: 0 56 | m_PVRFilterTypeIndirect: 0 57 | m_PVRFilterTypeAO: 0 58 | m_PVRFilteringGaussRadiusDirect: 1 59 | m_PVRFilteringGaussRadiusIndirect: 5 60 | m_PVRFilteringGaussRadiusAO: 2 61 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 62 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 63 | m_PVRFilteringAtrousPositionSigmaAO: 1 64 | -------------------------------------------------------------------------------- /Shaders/line color.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | // Unlit alpha-blended shader. 4 | // - no lighting 5 | // - no lightmap support 6 | // - no per-material color 7 | 8 | Shader "EcsLineRenderer/Line Color" { 9 | Properties { 10 | _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {} 11 | _Color ("Main Color", Color) = (1,1,1,1) 12 | } 13 | 14 | SubShader { 15 | Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} 16 | LOD 100 17 | 18 | ZWrite Off 19 | Blend SrcAlpha OneMinusSrcAlpha 20 | 21 | Pass { 22 | CGPROGRAM 23 | #pragma vertex vert 24 | #pragma fragment frag 25 | #pragma target 2.0 26 | #pragma multi_compile_fog 27 | #pragma multi_compile_instancing 28 | 29 | #include "UnityCG.cginc" 30 | 31 | struct appdata_t { 32 | float4 vertex : POSITION; 33 | float2 texcoord : TEXCOORD0; 34 | UNITY_VERTEX_INPUT_INSTANCE_ID 35 | }; 36 | 37 | struct v2f { 38 | float4 vertex : SV_POSITION; 39 | float2 texcoord : TEXCOORD0; 40 | UNITY_FOG_COORDS(1) 41 | UNITY_VERTEX_OUTPUT_STEREO 42 | }; 43 | 44 | sampler2D _MainTex; 45 | float4 _MainTex_ST; 46 | UNITY_INSTANCING_BUFFER_START(Props) 47 | UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color) 48 | UNITY_INSTANCING_BUFFER_END(Props) 49 | 50 | v2f vert (appdata_t v) 51 | { 52 | v2f o; 53 | UNITY_SETUP_INSTANCE_ID(v); 54 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 55 | o.vertex = UnityObjectToClipPos(v.vertex); 56 | o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); 57 | UNITY_TRANSFER_FOG(o,o.vertex); 58 | return o; 59 | } 60 | 61 | fixed4 frag (v2f i) : SV_Target 62 | { 63 | fixed4 col = tex2D(_MainTex, i.texcoord) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color); 64 | UNITY_APPLY_FOG(i.fogCoord, col); 65 | return col; 66 | } 67 | ENDCG 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] white line.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: '[EcsLineRenderer] white line' 11 | m_Shader: {fileID: 4800000, guid: f984f03111184a4478867e0ec34b6c09, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 2800000, guid: c28544402f30f674aa593707d4542bef, type: 3} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] green line.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: '[EcsLineRenderer] green line' 11 | m_Shader: {fileID: 4800000, guid: f984f03111184a4478867e0ec34b6c09, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 2800000, guid: c28544402f30f674aa593707d4542bef, type: 3} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 0, g: 1, b: 0.004989147, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Materials/[EcsLineRenderer] yellow line.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: '[EcsLineRenderer] yellow line' 11 | m_Shader: {fileID: 4800000, guid: f984f03111184a4478867e0ec34b6c09, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 1 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 2800000, guid: c28544402f30f674aa593707d4542bef, type: 3} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 0.84159184, b: 0, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Textures/line_round_cap.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3414d7772e890174e9ce0aa0fa678586 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 10 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: 1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | - serializedVersion: 3 75 | buildTarget: Standalone 76 | maxTextureSize: 2048 77 | resizeAlgorithm: 0 78 | textureFormat: -1 79 | textureCompression: 1 80 | compressionQuality: 50 81 | crunchedCompression: 0 82 | allowsAlphaSplitting: 0 83 | overridden: 0 84 | androidETC2FallbackOverride: 0 85 | forceMaximumCompressionQuality_BC6H_BC7: 0 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | bones: [] 92 | spriteID: 93 | internalID: 0 94 | vertices: [] 95 | indices: 96 | edges: [] 97 | weights: [] 98 | secondaryTextures: [] 99 | spritePackingTag: 100 | pSDRemoveMatte: 0 101 | pSDShowRemoveMatteOption: 0 102 | userData: 103 | assetBundleName: 104 | assetBundleVariant: 105 | -------------------------------------------------------------------------------- /Textures/line_smooth.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c28544402f30f674aa593707d4542bef 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 10 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: 1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | - serializedVersion: 3 75 | buildTarget: Standalone 76 | maxTextureSize: 2048 77 | resizeAlgorithm: 0 78 | textureFormat: -1 79 | textureCompression: 1 80 | compressionQuality: 50 81 | crunchedCompression: 0 82 | allowsAlphaSplitting: 0 83 | overridden: 0 84 | androidETC2FallbackOverride: 0 85 | forceMaximumCompressionQuality_BC6H_BC7: 0 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | bones: [] 92 | spriteID: 93 | internalID: 0 94 | vertices: [] 95 | indices: 96 | edges: [] 97 | weights: [] 98 | secondaryTextures: [] 99 | spritePackingTag: 100 | pSDRemoveMatte: 0 101 | pSDShowRemoveMatteOption: 0 102 | userData: 103 | assetBundleName: 104 | assetBundleVariant: 105 | -------------------------------------------------------------------------------- /Textures/line_square_cap.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1fe9bbb33ffe49644861fd8f68b0bcc8 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 10 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: 1 35 | aniso: 1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | - serializedVersion: 3 75 | buildTarget: Standalone 76 | maxTextureSize: 2048 77 | resizeAlgorithm: 0 78 | textureFormat: -1 79 | textureCompression: 1 80 | compressionQuality: 50 81 | crunchedCompression: 0 82 | allowsAlphaSplitting: 0 83 | overridden: 0 84 | androidETC2FallbackOverride: 0 85 | forceMaximumCompressionQuality_BC6H_BC7: 0 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | bones: [] 92 | spriteID: 93 | internalID: 0 94 | vertices: [] 95 | indices: 96 | edges: [] 97 | weights: [] 98 | secondaryTextures: [] 99 | spritePackingTag: 100 | pSDRemoveMatte: 0 101 | pSDShowRemoveMatteOption: 0 102 | userData: 103 | assetBundleName: 104 | assetBundleVariant: 105 | -------------------------------------------------------------------------------- /Samples/Entity workflow/EntityWorkflowSpawnerSimple.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Unity.Mathematics; 5 | using Unity.Entities; 6 | using Unity.Collections; 7 | using Unity.Transforms; 8 | 9 | using E7.ECS.LineRenderer; 10 | 11 | /// 12 | /// Instantiates line entities in default World.DefaultGameObjectInjectionWorld 13 | /// 14 | public class EntityWorkflowSpawnerSimple : MonoBehaviour 15 | { 16 | 17 | [SerializeField] Material _material = null; 18 | [SerializeField] [Min(0.01f)] float _lineWidth = 0.01f; 19 | [SerializeField] [Range(3,1000)] int _segments = 400; 20 | 21 | 22 | #if UNITY_EDITOR 23 | void OnDrawGizmos () 24 | { 25 | float theta = 0; 26 | var col = _material!=null ? _material.color : Color.white; 27 | col.a = math.max( col.a , 0.1f ); 28 | Gizmos.color = col; 29 | for( int i=0 ; i<_segments ; i++ ) 30 | { 31 | GeneratePoints( theta:ref theta , i:i , segments:_segments , matrix:transform.localToWorldMatrix , p0:out var p0 , p1:out var p1 ); 32 | Gizmos.DrawLine( p0 , p1 ); 33 | } 34 | } 35 | #endif 36 | 37 | void Start () 38 | { 39 | if( _material==null ) 40 | { 41 | Debug.LogWarning($"You forgot to set \'{nameof(_material)}\' field in the inspector!",gameObject); 42 | return; 43 | } 44 | 45 | InstantiateLines( material:_material , lineWidth:_lineWidth , segments:_segments , matrix:transform.localToWorldMatrix ); 46 | } 47 | 48 | static void InstantiateLines 49 | ( 50 | Material material , 51 | float lineWidth , 52 | int segments , 53 | float4x4 matrix 54 | ) 55 | { 56 | var world = World.DefaultGameObjectInjectionWorld; 57 | var command = world.EntityManager; 58 | 59 | var prefabArchetype = command.CreateArchetype( 60 | typeof(LineSegment) 61 | , typeof(LineStyle) 62 | , typeof(Prefab) 63 | ); 64 | var prefab = command.CreateEntity( prefabArchetype ); 65 | command.SetSharedComponentData( prefab , new LineStyle{ 66 | material = material 67 | } ); 68 | 69 | var instances = command.Instantiate( prefab , segments , Allocator.Temp ); 70 | { 71 | float theta = 0; 72 | for( int i=0 ; i Transform + NonUniformScale 45 | LineStyle -> RenderMesh 46 | Main Camera -> Rotation 47 | 48 | // Unity's built-in TransformSystemGroup 49 | 50 | Transform + Rotation + NonUniformScale -> LocalToWorld 51 | 52 | // Unity's Hybrid Renderer Package 53 | 54 | LocalToWorld + RenderMesh -> You see things on screen. 55 | ``` 56 | 57 | ![billboard](.Documentation/images/billboard.gif) 58 | 59 | ## Rendering 60 | 61 | The rendering is handled by `HybridRenderer` package, by generating `RenderMesh` shared component data for all your lines. So this package's work are all in simulation system group. 62 | 63 | For someone that is always looking for "pure ECS" approach to everything, no, it is not possible to see something on the screen in pure currently. Even the package is named **hybrid** renderer. I suggest you just drop the pure/hybrid wording altogether and just use what's the best. 64 | 65 | ## Minimum code to get a line from nothing 66 | 67 | ```csharp 68 | var e = EntityManager.CreateEntity(); 69 | EntityManager.AddComponentData(e, new LineSegment(math.float3(1, 1, 1), math.float3(1, 2, 1))); 70 | var mat = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/ECSLineRenderer/YellowLineMaterial.mat"); 71 | EntityManager.AddSharedComponentData(e, new LineStyle { material = mat }); 72 | ``` 73 | 74 | ## Info 75 | 76 | - Line width is in Unity's standard grid unit. 77 | - If position from and to are the same the system will not update the line. (Stays at previous position) 78 | 79 | ### GameObject Conversion / SubScene support 80 | 81 | This is a new and preferred way to author ECS content. `GameObjectEntity` has a performance problem to maintain a link to `GameObject`. `ConvertToEntity` has a problem that things disappear when you enter play mode if you want pure ECS at runtime (without inject mode, which would arrive the same performance problem) and also it is a problem in edit time that you don't know how it would end up. 82 | 83 | SubScene is the best of both worlds. Things with `IConvertGameObjectToEntity` inside SubScene get converted in play mode like `ConvertToEntity`, but they remains touchable in Hierarchy and anytime you do something they will get reconverted seamlessly. It feels like old `GameObjectEntity` approach except instead of synchronization it keeps reconverting in one way, then in the real build it works like pure ECS since you cannot touch Hierarchy in the real build. 84 | 85 | I have added `LineAuthoring : IConvertGameObjectToEntity` for this. See the green line in sample scene how this get converted to `LineSegment` and `LineStyle`. Since all systems here has `[ExecuteAlways]`, you can turn on `DOTS > Live Link Mode > Live Link Conversion in Edit Mode` then choose SceneView mode you like to see SubScene in action even in edit mode. 86 | 87 | ## Systems 88 | 89 | - `LineSegmentRegistrationSystem` : Having both `LineSegment` and `LineStyle` on the same `Entity` will qualify for a registration, which you will get a `RenderMesh` with migrated material from your `LineStyle` plus other TRS components. 90 | - `LineSegmentTransformSystem` : Calculate TRS which would then turns into `LocalToWorld` then `RenderMesh` use it. Based on information in `LineSegment`. Move your line by changing `LineSegment`'s data before this system. 91 | 92 | ## Limitations + problems 93 | 94 | Please see [Issues](https://github.com/5argon/ECSLineRenderer/issues) section. For instance, currently the billboard rotation is wrong. If anyone understand http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ you can send PR.. thanks. 95 | 96 | # This asset is sponsored by 97 | 98 | My other assets.. other than pull requests you can contribute by getting these. Thank you. 99 | 100 | - [Introloop](http://exceed7.com/introloop/) - Easily play looping music with intro section (without physically splitting them) (Unity 2017.0+) 101 | - [Native Audio](http://exceed7.com/native-audio/) - Lower audio latency via OS's native audio library. (Unity 2017.1+, iOS uses OpenAL / Android uses OpenSL ES) 102 | -------------------------------------------------------------------------------- /Samples/Entity workflow/EntityWorkflowSpawner.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Unity.Mathematics; 5 | using Unity.Entities; 6 | using Unity.Collections; 7 | using Unity.Transforms; 8 | using Unity.Rendering; 9 | 10 | using E7.ECS.LineRenderer; 11 | using MeshProvider = E7.ECS.LineRenderer.Internal.MeshProvider; 12 | 13 | /// 14 | /// Instantiates line entities in dedicated custom World. 15 | /// Sends line batch data manually to rendering api directly, giving great control over when and how lines are rendered 16 | /// 17 | public class EntityWorkflowSpawner : MonoBehaviour 18 | { 19 | 20 | [SerializeField] Material _material = null; 21 | [SerializeField] [Min(0.01f)] float _lineWidth = 0.1f; 22 | 23 | [SerializeField] [Range(3,1000)] int _segments = 1000; 24 | [SerializeField] float _worldScale = 1f; 25 | [SerializeField] float _tauFactor = 1f; 26 | [SerializeField] bool _spherize = false; 27 | 28 | static World _world = null; 29 | Entity[] _entities = null; 30 | 31 | 32 | #if UNITY_EDITOR 33 | void OnDrawGizmos () 34 | { 35 | float4x4 matrix = transform.localToWorldMatrix; 36 | float theta = 0; 37 | var col = _material!=null ? _material.color : Color.white; 38 | col.a = math.max( col.a , 0.1f ); 39 | Gizmos.color = col; 40 | for( int i=0 ; i<_segments ; i++ ) 41 | { 42 | GeneratePoints( 43 | theta: ref theta , 44 | tauFactor: _tauFactor , 45 | i: i , 46 | segments: _segments , 47 | worldScale: _worldScale , 48 | matrix: matrix , 49 | p0: out var p0 , 50 | p1: out var p1 51 | ); 52 | if( _spherize ) 53 | { 54 | p0 = math.normalize(p0) * _worldScale; 55 | p1 = math.normalize(p1) * _worldScale; 56 | } 57 | Gizmos.DrawLine( p0 , p1 ); 58 | } 59 | } 60 | void OnValidate () 61 | { 62 | if( Application.isPlaying && _world!=null && _entities!=null ) 63 | { 64 | var command = _world.EntityManager; 65 | 66 | // update lineWidth: 67 | for( int i=0 ; i<_entities.Length ; i++ ) 68 | { 69 | var segment = command.GetComponentData( _entities[i] );; 70 | segment.lineWidth = _lineWidth; 71 | command.SetComponentData( _entities[i] , segment ); 72 | } 73 | } 74 | } 75 | #endif 76 | 77 | void Start () 78 | { 79 | if( _material==null ) 80 | { 81 | Debug.LogWarning($"You forgot to set \'{nameof(_material)}\' field in the inspector!",gameObject); 82 | return; 83 | } 84 | 85 | if( _world==null ) 86 | { 87 | _world = new World($"{nameof(EntityWorkflowSpawner)} World"); 88 | DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups( 89 | _world 90 | , typeof(LineSegmentTransformSystem) 91 | ); 92 | ScriptBehaviourUpdateOrder.UpdatePlayerLoop( _world , UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop() ); 93 | } 94 | 95 | _entities = InstantiateLines( 96 | world: _world , 97 | material: _material , 98 | lineWidth: _lineWidth , 99 | segments: _segments , 100 | tauFactor: _tauFactor , 101 | worldScale: _worldScale , 102 | matrix: transform.localToWorldMatrix , 103 | spherize: _spherize 104 | ); 105 | } 106 | 107 | void Update () 108 | { 109 | if( _world!=null && _entities!=null ) 110 | { 111 | var command = _world.EntityManager; 112 | int numEntities = _entities.Length; 113 | var matrices = new Matrix4x4[ numEntities ]; 114 | for( int i=0 ; i( _entities[i] ); 117 | matrices[ i ] = ltr.Value; 118 | } 119 | Graphics.DrawMeshInstanced( 120 | mesh: MeshProvider.lineMesh , 121 | submeshIndex: 0 , 122 | material: _material , 123 | matrices: matrices 124 | ); 125 | } 126 | } 127 | 128 | void OnDestroy () 129 | { 130 | if( Application.isPlaying && _world!=null && _world.IsCreated && _entities!=null ) 131 | { 132 | var command = _world.EntityManager; 133 | foreach( var entity in _entities ) 134 | command.DestroyEntity( entity ); 135 | } 136 | } 137 | 138 | static Entity[] InstantiateLines 139 | ( 140 | World world , 141 | Material material , 142 | float lineWidth , 143 | int segments , 144 | float tauFactor , 145 | float worldScale , 146 | float4x4 matrix , 147 | bool spherize 148 | ) 149 | { 150 | var command = world.EntityManager; 151 | 152 | var prefabArchetype = command.CreateArchetype( 153 | typeof(LineSegment) 154 | , typeof(LocalToWorld) 155 | , typeof(Prefab) 156 | ); 157 | var prefab = command.CreateEntity( prefabArchetype ); 158 | var instances = command.Instantiate( prefab , segments , Allocator.Temp ); 159 | { 160 | float theta = 0; 161 | for( int i=0 ; i