├── .gitignore ├── Assets ├── Packages.meta └── Packages │ ├── ProceduralTree.meta │ └── ProceduralTree │ ├── Demo.meta │ ├── Demo │ ├── Demo.unity │ ├── Demo.unity.meta │ ├── Garden.asset │ ├── Garden.asset.meta │ ├── PTGarden.cs │ ├── PTGarden.cs.meta │ ├── PTGrowing.cs │ ├── PTGrowing.cs.meta │ ├── ProceduralTree.prefab │ └── ProceduralTree.prefab.meta │ ├── Materials.meta │ ├── Materials │ ├── Ground.mat │ ├── Ground.mat.meta │ ├── ProceduralTreeNormal.mat │ ├── ProceduralTreeNormal.mat.meta │ ├── ProceduralTreeStandard.mat │ ├── ProceduralTreeStandard.mat.meta │ ├── ProceduralTreeUV.mat │ └── ProceduralTreeUV.mat.meta │ ├── Scripts.meta │ ├── Scripts │ ├── Curve.meta │ ├── Curve │ │ ├── CatmullRomCurve.asset │ │ ├── CatmullRomCurve.asset.meta │ │ ├── CatmullRomCurve.cs │ │ ├── CatmullRomCurve.cs.meta │ │ ├── CurveBase.cs │ │ ├── CurveBase.cs.meta │ │ ├── FrenetFrame.cs │ │ └── FrenetFrame.cs.meta │ ├── Editor.meta │ ├── Editor │ │ ├── ProceduralModelingEditor.cs │ │ └── ProceduralModelingEditor.cs.meta │ ├── ProceduralModelingBase.cs │ ├── ProceduralModelingBase.cs.meta │ ├── ProceduralTree.cs │ └── ProceduralTree.cs.meta │ ├── Shaders.meta │ ├── Shaders │ ├── ProceduralTree.cginc │ ├── ProceduralTree.cginc.meta │ ├── ProceduralTreeNormal.shader │ ├── ProceduralTreeNormal.shader.meta │ ├── ProceduralTreeStandard.shader │ ├── ProceduralTreeStandard.shader.meta │ ├── ProceduralTreeUV.shader │ └── ProceduralTreeUV.shader.meta │ ├── Textures.meta │ └── Textures │ ├── Tree.jpg │ ├── Tree.jpg.meta │ ├── UVTextureChecker4096.png │ └── UVTextureChecker4096.png.meta ├── Captures ├── Demo.gif └── TreeData.png ├── LICENSE ├── ProceduralTree.unitypackage └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Pp]rojectSettings/ 6 | 7 | # Autogenerated VS/MD solution and project files 8 | *.csproj 9 | *.unityproj 10 | *.sln 11 | *.suo 12 | *.user 13 | *.userprefs 14 | *.pidb 15 | *.booproj 16 | 17 | # Unity3D Generated File On Crash Reports 18 | sysinfo.txt -------------------------------------------------------------------------------- /Assets/Packages.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af400a4ead170a24d899421df2452ce1 3 | folderAsset: yes 4 | timeCreated: 1494573600 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48fdaa191a3e6634bb5d375058a3243d 3 | folderAsset: yes 4 | timeCreated: 1494573643 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 212df6214dd2b4f3592c7b8b740c066f 3 | folderAsset: yes 4 | timeCreated: 1505887290 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/Demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fefec6e55634945bb8c84679c6f52637 3 | timeCreated: 1505885367 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/Garden.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!43 &4300000 4 | Mesh: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 0} 8 | m_Name: Garden 9 | serializedVersion: 8 10 | m_SubMeshes: 11 | - serializedVersion: 2 12 | firstByte: 0 13 | indexCount: 1176 14 | topology: 0 15 | firstVertex: 0 16 | vertexCount: 225 17 | localAABB: 18 | m_Center: {x: 0, y: 0, z: 0.23390535} 19 | m_Extent: {x: 1.5, y: 1.5, z: 0.18561581} 20 | m_Shapes: 21 | vertices: [] 22 | shapes: [] 23 | channels: [] 24 | fullWeights: [] 25 | m_BindPose: [] 26 | m_BoneNameHashes: 27 | m_RootBoneNameHash: 0 28 | m_MeshCompression: 0 29 | m_IsReadable: 1 30 | m_KeepVertices: 1 31 | m_KeepIndices: 1 32 | m_IndexBuffer: 00000f00010001000f001000010010000200020010001100020011000300030011001200030012000400040012001300040013000500050013001400050014000600060014001500060015000700070015001600070016000800080016001700080017000900090017001800090018000a000a00180019000a0019000b000b0019001a000b001a000c000c001a001b000c001b000d000d001b001c000d001c000e000e001c001d000f001e00100010001e001f0010001f00110011001f002000110020001200120020002100120021001300130021002200130022001400140022002300140023001500150023002400150024001600160024002500160025001700170025002600170026001800180026002700180027001900190027002800190028001a001a00280029001a0029001b001b0029002a001b002a001c001c002a002b001c002b001d001d002b002c001e002d001f001f002d002e001f002e00200020002e002f0020002f00210021002f003000210030002200220030003100220031002300230031003200230032002400240032003300240033002500250033003400250034002600260034003500260035002700270035003600270036002800280036003700280037002900290037003800290038002a002a00380039002a0039002b002b0039003a002b003a002c002c003a003b002d003c002e002e003c003d002e003d002f002f003d003e002f003e00300030003e003f0030003f00310031003f004000310040003200320040004100320041003300330041004200330042003400340042004300340043003500350043004400350044003600360044004500360045003700370045004600370046003800380046004700380047003900390047004800390048003a003a00480049003a0049003b003b0049004a003c004b003d003d004b004c003d004c003e003e004c004d003e004d003f003f004d004e003f004e00400040004e004f0040004f00410041004f005000410050004200420050005100420051004300430051005200430052004400440052005300440053004500450053005400450054004600460054005500460055004700470055005600470056004800480056005700480057004900490057005800490058004a004a00580059004b005a004c004c005a005b004c005b004d004d005b005c004d005c004e004e005c005d004e005d004f004f005d005e004f005e00500050005e005f0050005f00510051005f0060005100600052005200600061005200610053005300610062005300620054005400620063005400630055005500630064005500640056005600640065005600650057005700650066005700660058005800660067005800670059005900670068005a0069005b005b0069006a005b006a005c005c006a006b005c006b005d005d006b006c005d006c005e005e006c006d005e006d005f005f006d006e005f006e00600060006e006f0060006f00610061006f007000610070006200620070007100620071006300630071007200630072006400640072007300640073006500650073007400650074006600660074007500660075006700670075007600670076006800680076007700690078006a006a00780079006a0079006b006b0079007a006b007a006c006c007a007b006c007b006d006d007b007c006d007c006e006e007c007d006e007d006f006f007d007e006f007e00700070007e007f0070007f00710071007f008000710080007200720080008100720081007300730081008200730082007400740082008300740083007500750083008400750084007600760084008500760085007700770085008600780087007900790087008800790088007a007a00880089007a0089007b007b0089008a007b008a007c007c008a008b007c008b007d007d008b008c007d008c007e007e008c008d007e008d007f007f008d008e007f008e00800080008e008f0080008f00810081008f009000810090008200820090009100820091008300830091009200830092008400840092009300840093008500850093009400850094008600860094009500870096008800880096009700880097008900890097009800890098008a008a00980099008a0099008b008b0099009a008b009a008c008c009a009b008c009b008d008d009b009c008d009c008e008e009c009d008e009d008f008f009d009e008f009e00900090009e009f0090009f00910091009f00a0009100a00092009200a000a1009200a10093009300a100a2009300a20094009400a200a3009400a30095009500a300a4009600a50097009700a500a6009700a60098009800a600a7009800a70099009900a700a8009900a8009a009a00a800a9009a00a9009b009b00a900aa009b00aa009c009c00aa00ab009c00ab009d009d00ab00ac009d00ac009e009e00ac00ad009e00ad009f009f00ad00ae009f00ae00a000a000ae00af00a000af00a100a100af00b000a100b000a200a200b000b100a200b100a300a300b100b200a300b200a400a400b200b300a500b400a600a600b400b500a600b500a700a700b500b600a700b600a800a800b600b700a800b700a900a900b700b800a900b800aa00aa00b800b900aa00b900ab00ab00b900ba00ab00ba00ac00ac00ba00bb00ac00bb00ad00ad00bb00bc00ad00bc00ae00ae00bc00bd00ae00bd00af00af00bd00be00af00be00b000b000be00bf00b000bf00b100b100bf00c000b100c000b200b200c000c100b200c100b300b300c100c200b400c300b500b500c300c400b500c400b600b600c400c500b600c500b700b700c500c600b700c600b800b800c600c700b800c700b900b900c700c800b900c800ba00ba00c800c900ba00c900bb00bb00c900ca00bb00ca00bc00bc00ca00cb00bc00cb00bd00bd00cb00cc00bd00cc00be00be00cc00cd00be00cd00bf00bf00cd00ce00bf00ce00c000c000ce00cf00c000cf00c100c100cf00d000c100d000c200c200d000d100c300d200c400c400d200d300c400d300c500c500d300d400c500d400c600c600d400d500c600d500c700c700d500d600c700d600c800c800d600d700c800d700c900c900d700d800c900d800ca00ca00d800d900ca00d900cb00cb00d900da00cb00da00cc00cc00da00db00cc00db00cd00cd00db00dc00cd00dc00ce00ce00dc00dd00ce00dd00cf00cf00dd00de00cf00de00d000d000de00df00d000df00d100d100df00e000 33 | m_Skin: [] 34 | m_VertexData: 35 | m_CurrentChannels: 11 36 | m_VertexCount: 225 37 | m_Channels: 38 | - stream: 0 39 | offset: 0 40 | format: 0 41 | dimension: 3 42 | - stream: 0 43 | offset: 12 44 | format: 0 45 | dimension: 3 46 | - stream: 0 47 | offset: 0 48 | format: 0 49 | dimension: 0 50 | - stream: 0 51 | offset: 24 52 | format: 0 53 | dimension: 2 54 | - stream: 0 55 | offset: 0 56 | format: 0 57 | dimension: 0 58 | - stream: 0 59 | offset: 0 60 | format: 0 61 | dimension: 0 62 | - stream: 0 63 | offset: 0 64 | format: 0 65 | dimension: 0 66 | - stream: 0 67 | offset: 0 68 | format: 0 69 | dimension: 0 70 | m_DataSize: 7200 71 | _typelessdata: 0000c0bf0000c0bf46386e3ef9c22a3e1c2174bef9ec74bf00000000000000004992a4bf0000c0bfa93b8a3eeb0b7cbc249177bee15f78bf2549923d00000000922489bf0000c0bf28893d3e23ab14be13f974bea1c575bf2549123e00000000b66d5bbf0000c0bf5aec833e2b93c83e305764be2e8464bfb86d5b3e00000000489224bf0000c0bfd329ca3efe88893ea95f87be841e6dbf2549923e00000000b66ddbbe0000c0bf42f4a23e15cdbfbe036579be000665bf6edbb63e00000000b06d5bbe0000c0bf46ee443e5ee789be720121be373b73bfb86ddb3e00000000000000000000c0bf46386e3e0190633e88641fbd526679bf0000003f00000000bc6d5b3e0000c0bf1fc18b3e1897f9ba6717a33dbf2f7fbf2549123f00000000bc6ddb3e0000c0bff260293ecc298bbe035e553eae8470bf4a92243f000000004a92243f0000c0bf8aa4253efa76f43d8fee9f3e3b4371bf6edb363f00000000b96d5b3f0000c0bf512c6d3eef2fdd3d3f247c3e9d9276bf9324493f000000009424893f0000c0bf22894a3edd2256be8d10193ee86577bfb86d5b3f000000004a92a43f0000c0bf764b113ec77d6f3c76a7613ec7ad79bfdcb66d3f000000000000c03f0000c0bf46386e3e1d47bd3e80a7703e482166bf0000803f000000000000c0bf4992a4bf818a373ee9242c3e299d50bea1e876bf000000002549923d4992a4bf4992a4bf8dc95d3e6fcbddbd962e40be01eb79bf2549923d2549923d922489bf4992a4bf62db063e5fb9e9bc026441be79497bbf2549123e2549923db66d5bbf4992a4bfa5f6503ec1a6d63e4e0438be48d163bfb86d5b3e2549923d489224bf4992a4bf0be8a83e02b9003e724054be355d78bf2549923e2549923db66ddbbe4992a4bfbac7863ebbaea9bea6bf8cbd12e470bf6edbb63e2549923db06d5bbe4992a4bfd9a22a3e943517bdbaf7193ec4e97cbfb86ddb3e2549923d000000004992a4bf46386e3e938e4d3ed4a2cb3d717e79bf0000003f2549923dbc6d5b3e4992a4bfd7e6983efba401be5b649fbd3d287dbf2549123f2549923dbc6ddb3e4992a4bf6c3a653ebfd6c5bdee33933cdec27ebf4a92243f2549923d4a92243f4992a4bfc6cf743e2d93353edeb9153eab2579bf6edb363f2549923db96d5b3f4992a4bfcddd8c3e215cabbd3f7a04bc09187fbf9324493f2549923d9424893f4992a4bf732a673ece1b5abea499e7bdcd7178bfb86d5b3f2549923d4a92a43f4992a4bf03594d3e79f26c3e4b33ba3d56f677bfdcb66d3f2549923d0000c03f4992a4bf0673923e7fe6be3e06af1a3e025f6abf0000803f2549923d0000c0bf922489bf09da193e53542f3ebeb09a3d317a7bbf000000002549123e4992a4bf922489bf1519403e1f0adfbd7565363ecd5b7abf2549923d2549123e922489bf922489bfd655d23d995af1bc9922363e18ce7bbf2549123e2549123eb66d5bbf922489bf7d04333eb51cd33e1e9b233e4a9c65bfb86d5b3e2549123e489224bf922489bf606a993e7247353e5700e03d5b657abf2549923e2549123eb66ddbbe922489bff03b993e55e543beb418653d13dd7abf6edbb63e2549123eb06d5bbe922489bf01558b3e834b8cbd8a487f3c135e7fbfb86ddb3e2549123e00000000922489bf46386e3e93355ebdaf9e04beb8767dbf0000003f2549123ebc6d5b3e922489bf89c6453e96c7d5bd8c21c0bd59777dbf2549123f2549123ebc6ddb3e922489bfcfb1433ed560f23d8aba093eacdb7bbf4a92243f2549123e4a92243f922489bfca83813e2570d63db79c323e7aa57abf6edb363f2549123eb96d5b3f922489bf4a68523e55228cbe5464843bf73876bf9324493f2549123e9424893f922489bf1477033ee31fa0bd0f9284bcc62e7fbfb86d5b3f2549123e4a92a43f922489bf8b98653e4be6ab3eda02d2bad32371bfdcb66d3f2549123e0000c03f922489bf414ba13e42b8a43e95b049be5e166dbf0000803f2549123e0000c0bfb66d5bbf5aec833e0753193ed4d8f23e85165ebf00000000b86d5b3e4992a4bfb66d5bbf08c4963e4c740abefe8adf3eefb163bf2549923db86d5b3e922489bfb66d5bbf9226563ef5053abd5e76c43e131e6cbf2549123eb86d5b3eb66d5bbfb66d5bbfef9c8f3e9c749e3efb649e3e433066bfb86d5b3eb86d5b3e489224bfb66d5bbfe96ea93ef0a610bd8a0e1e3e3cc57cbf2549923eb86d5b3eb66ddbbeb66d5bbf031a6d3e05ae99be844044bd3de373bf6edbb63eb86d5b3eb06d5bbeb66d5bbf0f9a573ec9d6aabd07f8c7bd56e17dbfb86ddb3eb86d5b3e00000000b66d5bbffda76d3edea8a13c84537ebdc3747fbf0000003fb86d5b3ebc6d5b3eb66d5bbf393d823eff20e33dc0ec9d3d60a77dbf2549123fb86d5b3ebc6ddb3eb66d5bbfc3618c3e36e2663ecc094c3ec92274bf4a92243fb86d5b3e4a92243fb66d5bbf719bb13e8a8c053cdce5483e28047bbf6edb363fb86d5b3eb96d5b3fb66d5bbfc6208f3ece6cbabe0572e33dd0b96cbf9324493fb86d5b3e9424893fb66d5bbf276e2a3ef09e3abec81ff4ba56b67bbfb86d5b3fb86d5b3e4a92a43fb66d5bbf97e6293e3ab1323d199eadbec39270bfdcb66d3fb86d5b3e0000c03fb66d5bbfd897543eb6f4103e16d0f8bed3c85cbf0000803fb86d5b3e0000c0bf489224bfd329ca3ea9ab733cb9f8643e2e7d79bf000000002549923e4992a4bf489224bfeb40c33eaa9b94be3b308bbd5d5c74bf2549923d2549923e922489bf489224bf53388c3e7d325bbdf19db7bdc7997ebf2549123e2549923eb66d5bbf489224bfa02bb23e1389973edee9c5bcd37374bfb86d5b3e2549923e489224bf489224bf7beecc3ef347c6bd3eb9d73dd05d7dbf2549923e2549923eb66ddbbe489224bf75b2863e5077b4bef9a63d3ef5d46abf6edbb63e2549923eb06d5bbe489224bfbafc453e164f64be6243623dad2779bfb86ddb3e2549923e00000000489224bffeb62e3e528224bd25a267be032779bf0000003f2549923ebc6d5b3e489224bf55f16d3e17fc6e3e7bcc6dbe36ba71bf2549123f2549923ebc6ddb3e489224bfb434943e48c2943ecf0bf1bda91873bf4a92243f2549923e4a92243f489224bf3e7fac3e260d9dbdbb0437be9e1c7bbf6edb363f2549923eb96d5b3f489224bf238c893ec376c0bec92f44be491968bf9324493f2549923e9424893f489224bf78a5253e457eb2be12a138be4a756bbfb86d5b3f2549923e4a92a43f489224bf43cb453d90ca21beea6b86be86af73bfdcb66d3f2549923e0000c03f489224bfd039903dd295403e0ee87fbd2bec7abf0000803f2549923e0000c0bfb66ddbbe42f4a23ea02143be49d1e8beebb85ebf000000006edbb63e4992a4bfb66ddbbeec5c823ec44b8ebe7affeabe150758bf2549923d6edbb63e922489bfb66ddbbec923393edeccb83da56ba1beebd771bf2549123e6edbb63eb66d5bbfb66ddbbe855c8d3e9f3ee33e6a77febd063063bfb86d5b3e6edbb63e489224bfb66ddbbe7acbd63e66e0e33db2f2e93c264e7ebf2549923e6edbb63eb66ddbbeb66ddbbe3b7ab83e290bcbbe06bfd93bc9006bbf6edbb63e6edbb63eb06d5bbeb66ddbbea3a76a3efc07f7be768b4abe8c705abfb86ddb3e6edbb63e00000000b66ddbbe5b2e9b3db63811be2baf94be3a4372bf0000003f6edbb63ebc6d5b3eb66ddbbed8510b3ec746cb3e737d41bdc1a56abf2549123f6edbb63ebc6ddb3eb66ddbbefd977d3e9ac79a3e5fd7b53d13f672bf4a92243f6edbb63e4a92243fb66ddbbe2621833e499a17be7b61c13c531b7dbf6edb363f6edbb63eb96d5b3fb66ddbbe6be83e3e6f059bbe5710673d598e73bf9324493f6edbb63e9424893fb66ddbbe75b40f3eddb08ebe192a493ea4a870bfb86d5b3f6edbb63e4a92a43fb66ddbbeb7198b3d76ed0abc110cb13e943270bfdcb66d3f6edbb63e0000c03fb66ddbbe0788163e116ba53e767ce43ed7a455bf0000803f6edbb63e0000c0bfb06d5bbedb0b3e3ec45250bef127c8bec4cc65bf00000000b86ddb3e4992a4bfb06d5bbebf0a143ec58505be0d4482bea15075bf2549923db86ddb3e922489bfb06d5bbedae6193ea9c1a83e3f25493d145e71bf2549123eb86ddb3eb66d5bbfb06d5bbe1ff7863e66eff03e4d8dca3de37560bfb86d5b3eb86ddb3e489224bfb06d5bbea7b3c03ee4965ebd6b2d4cbe31797abf2549923eb86ddb3eb66ddbbeb06d5bbe96f58a3e1b23f0be9813b2be80d34fbf6edbb63eb86ddb3eb06d5bbeb06d5bbe9f780b3e41c3cfbec63645bee0b864bfb86ddb3eb86ddb3e00000000b06d5bbeb3398b3d15d3373e5db13a3e837a77bf0000003fb86ddb3ebc6d5b3eb06d5bbe0f6a653e6b1e003ff2188f3e72c451bf2549123fb86ddb3ebc6ddb3eb06d5bbeaa28b13e6e29823e3aed893e7aca6dbf4a92243fb86ddb3e4a92243fb06d5bbeac38b03ee70a63bef318073e325577bf6edb363fb86ddb3eb96d5b3fb06d5bbecd008c3e2c4d73bec3fcb53d55a077bf9324493fb86ddb3e9424893fb06d5bbe2d9c783e58b000be3ef7873ed2b374bfb86d5b3fb86ddb3e4a92a43fb06d5bbefd64483e77681b3e8434f83ecc825cbfdcb66d3fb86ddb3e0000c03fb06d5bbe8fa3923ee7b39b3e77ba003f19224fbf0000803fb86ddb3e0000c0bf0000000086e8173ebc9620be0792aa3cb3c67cbf000000000000003f4992a4bf00000000c444f13d08c89d3d434b063e7b057dbf2549923d0000003f922489bf00000000c4866f3ebfe7da3e6e973c3e7d9162bf2549123e0000003fb66d5bbf00000000fd20a83e8da0603e0cec04bd65a079bfb86d5b3e0000003f489224bf0000000047e5993ea03eb0bec6d3b2bec81a5fbf2549923e0000003fb66ddbbe0000000065532d3eb6b7acbee55260beca606abf6edbb63e0000003fb06d5bbe000000002e0a153ed3f50fbc6c82803e78cb77bfb86ddb3e0000003f000000000000000086e8173e6a42823ec9e0ad3e45cf67bf0000003f0000003fbc6d5b3e00000000c62b883e6bfcc33eb87f193dc64e6cbf2549123f0000003fbc6ddb3e00000000d4f9bc3ecfcdcb3d9f243ebe2c417abf4a92243f0000003f4a92243f000000006ae4933e15d8a3be34669dbe306a65bf6edb363f0000003fb96d5b3f000000002a42633e1dd953bda5704fbe9d577abf9324493f0000003f9424893f0000000037c58f3ebc636b3e1c74093e6ac376bfb86d5b3f0000003f4a92a43f000000008f98ae3ea225853e167e833eda496ebfdcb66d3f0000003f0000c03f00000000e46bcd3e2853133eaabe2ebde4197dbf0000803f0000003f0000c0bfbc6d5b3ed955673eccff89be4777493e7a5371bf000000002549123f4992a4bfbc6d5b3e41dd183e0c36da3cf2eb8e3de9487fbf2549923d2549123f922489bfbc6d5b3e109c713ea8df863ee0e922be909373bf2549123e2549123fb66d5bbfbc6d5b3ec6e48e3e697d91bd26fbbfbed49f6cbfb86d5b3e2549123f489224bfbc6d5b3e351d473e0cba8ebe8b5faabe3c9f66bf2549923e2549123fb66ddbbebc6d5b3e11f6293ef609003e0df5113db7d37dbf6edbb63e2549123fb06d5bbebc6d5b3e045a873e52fa2b3ed965773ed8aa74bfb86ddb3e2549123f00000000bc6d5b3e30346a3e71a848bd7ff3673d06487fbf0000003f2549123fbc6d5b3ebc6d5b3eba2c4b3e7580073ede2853be653278bf2549123f2549123fbc6ddb3ebc6d5b3e3c18923ef1cfa8bbb2b97dbe790378bf4a92243f2549123f4a92243fbc6d5b3e51e0433e2f9c74beec9cfcbd3c9376bf6edb363f2549123fb96d5b3fbc6d5b3e7e202e3e82f5583e3cceff3de32278bf9324493f2549123f9424893fbc6d5b3e4f39923ed81da03e4bf7303ee5196fbfb86d5b3f2549123f4a92a43fbc6d5b3ea564a03e9ad125bd5fc534be23c47bbfdcb66d3f2549123f0000c03fbc6d5b3e8da3923e769b3dbe50c6d6be708063bf0000803f2549123f0000c0bfbc6ddb3e9e88803e69a9cabec2b40d3e336868bf000000004a92243f4992a4bfbc6ddb3e67cb183e850cedbd3352483e874c79bf2549923d4a92243f922489bfbc6ddb3e7db91a3ed40b0c3c670c3fbb54fd7fbf2549123e4a92243fb66d5bbfbc6ddb3e90fe263e005a28be15e549beb46b77bfb86d5b3e4a92243f489224bfbc6ddb3e816dfb3d8f3242bcb3c1a5bd60247fbf2549923e4a92243fb66ddbbebc6ddb3e33da2c3effcbae3e7566f33d0fb06ebf6edbb63e4a92243fb06d5bbebc6ddb3e616d883e13fa0a3debbc0abda3b47fbfb86ddb3e4a92243f00000000bc6ddb3e94cc5e3ecd445ebea01048be0ed774bf0000003f4a92243fbc6d5b3ebc6ddb3e8be9343ed792043ef91344be471179bf2549123f4a92243fbc6ddb3ebc6ddb3e7656873e6424643d72cd45be01c67abf4a92243f4a92243f4a92243fbc6ddb3e78ce783e1679913cc33e9bbce5e97fbf6edb363f4a92243fb96d5b3fbc6ddb3e9c958d3eb62ca73e45b8293e5f386ebf9324493f4a92243f9424893fbc6ddb3e7183b83e741ebe3c096b213d6dbb7fbfb86d5b3f4a92243f4a92a43fbc6ddb3e4a857b3eb798c7be935985be001f62bfdcb66d3f4a92243f0000c03fbc6ddb3ef260293ef23a8dbece0483be10306dbf0000803f4a92243f0000c0bf4a92243ff3dfa53e55ca87be6030533ea41e71bf000000006edb363f4992a4bf4a92243f3d9a913e3c18e7bd9ab5713e491577bf2549923d6edb363f922489bf4a92243fbae1653e6f6f3cbec8017e3ed17b73bf2549123e6edb363fb66d5bbf4a92243f6d9e163e25ed65bef6e5203ee53276bfb86d5b3e6edb363f489224bf4a92243ff265183e4dd6293ea340683ec2af75bf2549923e6edb363fb66ddbbe4a92243f26746f3e35ad653e893c343eea5f75bf6edbb63e6edb363fb06d5bbe4a92243f36c85c3e133183bebe6617be9e8a74bfb86ddb3e6edb363f000000004a92243f57e5083e497750bee9513bbea23976bf0000003f6edb363fbc6d5b3e4a92243f3aa6fe3d4133203e26c120bde9a57cbf2549123f6edb363fbc6ddb3e4a92243f85b5223e3e6a733d38b8cebddf3c7ebf4a92243f6edb363f4a92243f4a92243ff3db363ee0ba273e06750ebec2047abf6edb363f6edb363fb96d5b3f4a92243fa7078f3e6e66b43e9d8810bea8d76cbf9324493f6edb363f9424893f4a92243f5dcdaf3edc4526beb00858bee8c276bfb86d5b3f6edb363f4a92a43f4a92243fa657453e678ac1be8163f4bd3e076bbfdcb66d3f6edb363f0000c03f4a92243f8aa4253ebe9120bdd0fed83d6e5c7ebf0000803f6edb363f0000c0bfb96d5b3f5b66833e2052a83d840d3bbecbcf7abf000000009324493f4992a4bfb96d5b3f70579b3ea824a23ddecb96bdd27f7ebf2549923d9324493f922489bfb96d5b3fc06da23eaba03abe29f80a3d00907bbf2549123e9324493fb66d5bbfb96d5b3f7bb7553e5b965bbe4845573db3ae79bfb86d5b3e9324493f489224bfb96d5b3fde6f583eda9b4e3e5820f93d2fcb78bf2549923e9324493fb66ddbbeb96d5b3f5ce08f3e9f235f3cde7bc43d96cb7ebf6edbb63e9324493fb06d5bbeb96d5b3f3ec43d3e1d78a8bede95293d258371bfb86ddb3e9324493f00000000b96d5b3f73e60b3e9b8aa53c5c5a753e3a7d78bf0000003f9324493fbc6d5b3eb96d5b3f0b374f3e9980273e7f05ba3e05cd6abf2549123f9324493fbc6ddb3eb96d5b3f3ccc443e029be9bdba36703e2d2377bf4a92243f9324493f4a92243fb96d5b3fd28b083e4a93aa3b84becfbc0aea7fbf6edb363f9324493fb96d5b3fb96d5b3f419b563ea235903e684639bea73a71bf9324493f9324493f9424893fb96d5b3fd0e18f3ebea7c0bd205142be32317abfb86d5b3f9324493f4a92a43fb96d5b3ff2be473e764225be596f35bdba637cbfdcb66d3f9324493f0000c03fb96d5b3f512c6d3ea821393e9d821ebcedc47bbf0000803f9324493f0000c0bf9424893f28893d3ea45f483e6ea0c6bd04d279bf00000000b86d5b3f4992a4bf9424893fcf97673e762d943da94fffbda4537dbf2549923db86d5b3f922489bf9424893f984d823ee8b355be0bc6a1becfef6cbf2549123eb86d5b3fb66d5bbf9424893f93323a3ed70dc7bcaa9338bee3ba7bbfb86d5b3eb86d5b3f489224bf9424893f6f67603e5d54a43e7232b63d526271bf2549923eb86d5b3fb66ddbbe9424893f4f379d3eb1b20bbc5f05243e6aaf7cbf6edbb63eb86d5b3fb06d5bbe9424893f7cd46a3e5c3126be2f2a913e1ff471bfb86ddb3eb86d5b3f000000009424893fd2e96c3e8d413d3ea0d6da3ec18c62bf0000003fb86d5b3fbc6d5b3e9424893fda44a13ecf153e3d6547a63efad471bf2549123fb86d5b3fbc6ddb3e9424893f2115903e7fedb3bee19f743dfa2e6fbf4a92243fb86d5b3f4a92243f9424893ff1331c3e7a2236be2066bdbd97cd7abf6edb363fb86d5b3fb96d5b3f9424893fcbc0353e426c403e635330be988b77bf9324493fb86d5b3f9424893f9424893ff1026f3ecaf5d9bd624e94be758173bfb86d5b3fb86d5b3f4a92a43f9424893f90601c3e0d3794bd803198beb1b973bfdcb66d3fb86d5b3f0000c03f9424893f22894a3ed8b8793e179984be3c416fbf0000803fb86d5b3f0000c0bf4a92a43fac3b8a3e6ad2f0bdd3c14e3d35e57dbf00000000dcb66d3f4992a4bf4a92a43fc869583e97fd77be900f4abe2f3073bf2549923ddcb66d3f922489bf4a92a43f8ef4f23d031525be3fe04dbe765a77bf2549123edcb66d3fb66d5bbf4a92a43fd5a01e3e2c22a73e62b22d3e560c6ebfb86d5b3edcb66d3f489224bf4a92a43fe57e8b3e4d09ba3ea691743e548866bf2549923edcb66d3fb66ddbbe4a92a43f5960ac3ea94b4abdc65aa63c7fa27fbf6edbb63edcb66d3fb06d5bbe4a92a43fa5c9a13ea604183c5ae2203d9bca7fbfb86ddb3edcb66d3f000000004a92a43f16e7b13e354b063eeac79d3d7d057dbf0000003fdcb66d3fbc6d5b3e4a92a43fe232a43ef87578be9cf6f7bd7e6876bf2549123fdcb66d3fbc6ddb3e4a92a43f501e623e3ff9e0be235955be04b15fbf4a92243fdcb66d3f4a92243f4a92a43f86b6f33db14cebbdcee078bd1ed47dbf6edb363fdcb66d3fb96d5b3f4a92a43fabee0a3e8963e13d0f300e3d2b4a7ebf9324493fdcb66d3f9424893f4a92a43f5265023e86b048bebdcf46bd43ba7abfb86d5b3fdcb66d3f4a92a43f4a92a43f55ae833da4e0683c91d1b4bb61f87fbfdcb66d3fdcb66d3f0000c03f4a92a43f764b113e288cb43ebe17253e0bf96bbf0000803fdcb66d3f0000c0bf0000c03f46386e3e77e07fbe249c1ebed1af74bf000000000000803f4992a4bf0000c03f818a373e486586be801948bdd7b476bf2549923d0000803f922489bf0000c03f09da193e7be12c3e52dd7a3e286874bf2549123e0000803fb66d5bbf0000c03f5f66833e32bbc63ec8f8ad3ece4e5bbfb86d5b3e0000803f489224bf0000c03ff2dfa53eb9eab93d16e6dc3c79d97ebf2549923e0000803fb66ddbbe0000c03f9a88803e3db21abeec18b6be871d6cbf6edbb63e0000803fb06d5bbe0000c03fb21a753e868c133e0f488bbe799173bfb86ddb3e0000803f000000000000c03f0344a23e5091aa3cc29620beb2c67cbf0000003f0000803fbc6d5b3e0000c03f56328f3ee9e1b6be7ffa47beb1d369bf2549123f0000803fbc6ddb3e0000c03ff260293e1cc7a4be9a25ccbd700871bf4a92243f0000803f4a92243f0000c03f8aa4253e7f2dfc3d43078a3e8e7f74bf6edb363f0000803fb96d5b3f0000c03f512c6d3e863b233de349c13e4ad66cbf9324493f0000803f9424893f0000c03f22894a3e44c760beb0bda03eb1786cbfb86d5b3f0000803f4a92a43f0000c03f764b113ebd17253e288cb43e0bf96bbfdcb66d3f0000803f0000c03f0000c03f46386e3e2804ba3e2804ba3ee89f5bbf0000803f0000803f 72 | m_CompressedMesh: 73 | m_Vertices: 74 | m_NumItems: 0 75 | m_Range: 0 76 | m_Start: 0 77 | m_Data: 78 | m_BitSize: 0 79 | m_UV: 80 | m_NumItems: 0 81 | m_Range: 0 82 | m_Start: 0 83 | m_Data: 84 | m_BitSize: 0 85 | m_Normals: 86 | m_NumItems: 0 87 | m_Range: 0 88 | m_Start: 0 89 | m_Data: 90 | m_BitSize: 0 91 | m_Tangents: 92 | m_NumItems: 0 93 | m_Range: 0 94 | m_Start: 0 95 | m_Data: 96 | m_BitSize: 0 97 | m_Weights: 98 | m_NumItems: 0 99 | m_Data: 100 | m_BitSize: 0 101 | m_NormalSigns: 102 | m_NumItems: 0 103 | m_Data: 104 | m_BitSize: 0 105 | m_TangentSigns: 106 | m_NumItems: 0 107 | m_Data: 108 | m_BitSize: 0 109 | m_FloatColors: 110 | m_NumItems: 0 111 | m_Range: 0 112 | m_Start: 0 113 | m_Data: 114 | m_BitSize: 0 115 | m_BoneIndices: 116 | m_NumItems: 0 117 | m_Data: 118 | m_BitSize: 0 119 | m_Triangles: 120 | m_NumItems: 0 121 | m_Data: 122 | m_BitSize: 0 123 | m_UVInfo: 0 124 | m_LocalAABB: 125 | m_Center: {x: 0, y: 0, z: 0.23390535} 126 | m_Extent: {x: 1.5, y: 1.5, z: 0.18561581} 127 | m_MeshUsageFlags: 0 128 | m_BakedConvexCollisionMesh: 129 | m_BakedTriangleCollisionMesh: 130 | m_MeshOptimized: 0 131 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/Garden.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d26714c6deba4a3cb8ebbc9ad5d612f 3 | timeCreated: 1505887745 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 0 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/PTGarden.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | using UnityEngine; 5 | using UnityEngine.Rendering; 6 | 7 | namespace ProceduralModeling { 8 | 9 | public class PTGarden : MonoBehaviour { 10 | 11 | [SerializeField] Camera cam; 12 | [SerializeField] List prefabs; 13 | [SerializeField] Vector2 scaleRange = new Vector2(1f, 1.2f); 14 | 15 | const string SHADER_PATH = "Hidden/Internal-Colored"; 16 | 17 | Material lineMaterial = null; 18 | MeshCollider col = null; 19 | Vector3[] vertices; 20 | int[] triangles; 21 | 22 | bool hit; 23 | Vector3 point; 24 | Vector3 normal; 25 | Quaternion rotation; 26 | 27 | void Update () { 28 | var mouse = Input.mousePosition; 29 | var ray = cam.ScreenPointToRay(mouse); 30 | RaycastHit info; 31 | hit = col.Raycast(ray, out info, float.MaxValue); 32 | if(hit) { 33 | point = info.point; 34 | var t = info.triangleIndex * 3; 35 | var a = triangles[t]; 36 | var b = triangles[t + 1]; 37 | var c = triangles[t + 2]; 38 | var va = vertices[a]; 39 | var vb = vertices[b]; 40 | var vc = vertices[c]; 41 | normal = transform.TransformDirection(Vector3.Cross(vb - va, vc - va)); 42 | rotation = Quaternion.LookRotation(normal); 43 | } 44 | 45 | if(Input.GetMouseButtonUp(0) && hit) { 46 | var go = Instantiate(prefabs[Random.Range(0, prefabs.Count)]) as GameObject; 47 | go.transform.position = point; 48 | go.transform.localScale = Vector3.one * Random.Range(scaleRange.x, scaleRange.y); 49 | go.transform.localRotation = Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.up); 50 | 51 | var tree = go.GetComponent(); 52 | tree.Data.randomSeed = Random.Range(0, 300); 53 | } 54 | 55 | } 56 | 57 | const int resolution = 16; 58 | const float pi2 = Mathf.PI * 2f; 59 | const float radius = 0.5f; 60 | Color color = new Color(0.6f, 0.75f, 1f); 61 | 62 | void OnRenderObject () { 63 | if(!hit) return; 64 | 65 | CheckInit(); 66 | 67 | lineMaterial.SetPass(0); 68 | lineMaterial.SetInt("_ZTest", (int)CompareFunction.Always); 69 | 70 | GL.PushMatrix(); 71 | GL.Begin(GL.LINES); 72 | GL.Color(color); 73 | 74 | for(int i = 0; i < resolution; i++) { 75 | var cur = (float)i / resolution * pi2; 76 | var next = (float)(i + 1) / resolution * pi2; 77 | var p1 = rotation * new Vector3(Mathf.Cos(cur), Mathf.Sin(cur), 0f); 78 | var p2 = rotation * new Vector3(Mathf.Cos(next), Mathf.Sin(next), 0f); 79 | GL.Vertex(point + p1 * radius); 80 | GL.Vertex(point + p2 * radius); 81 | } 82 | 83 | GL.End(); 84 | GL.PopMatrix(); 85 | } 86 | 87 | void OnEnable () { 88 | col = GetComponent(); 89 | var mesh = GetComponent().sharedMesh; 90 | vertices = mesh.vertices; 91 | triangles = mesh.triangles; 92 | } 93 | 94 | void CheckInit () { 95 | if(lineMaterial == null) { 96 | Shader shader = Shader.Find(SHADER_PATH); 97 | if (shader == null) return; 98 | lineMaterial = new Material(shader); 99 | lineMaterial.hideFlags = HideFlags.HideAndDontSave; 100 | } 101 | } 102 | 103 | } 104 | 105 | } 106 | 107 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/PTGarden.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aeeedfdf9979a41a1949618046d9fbc5 3 | timeCreated: 1505887296 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/PTGrowing.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace ProceduralModeling { 6 | 7 | [RequireComponent (typeof(MeshRenderer))] 8 | public class PTGrowing : MonoBehaviour { 9 | 10 | Material material; 11 | 12 | const string kGrowingKey = "_T"; 13 | 14 | void OnEnable () { 15 | material = GetComponent().material; 16 | material.SetFloat(kGrowingKey, 0f); 17 | } 18 | 19 | void Start () { 20 | StartCoroutine(IGrowing(3f)); 21 | } 22 | 23 | IEnumerator IGrowing(float duration) { 24 | yield return 0; 25 | var time = 0f; 26 | while(time < duration) { 27 | yield return 0; 28 | material.SetFloat(kGrowingKey, time / duration); 29 | time += Time.deltaTime; 30 | } 31 | material.SetFloat(kGrowingKey, 1f); 32 | } 33 | 34 | void OnDestroy() { 35 | if(material != null) { 36 | Destroy(material); 37 | material = null; 38 | } 39 | } 40 | 41 | } 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/PTGrowing.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fade3408622cc489389f11fa87ef789f 3 | timeCreated: 1505888487 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/ProceduralTree.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_ParentPrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1856826850138188} 13 | m_IsPrefabParent: 1 14 | --- !u!1 &1856826850138188 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_PrefabParentObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 5 20 | m_Component: 21 | - component: {fileID: 4608705280554932} 22 | - component: {fileID: 33019469920901372} 23 | - component: {fileID: 23659821880543676} 24 | - component: {fileID: 114952813105359896} 25 | - component: {fileID: 114820971152666198} 26 | m_Layer: 0 27 | m_Name: ProceduralTree 28 | m_TagString: Untagged 29 | m_Icon: {fileID: 0} 30 | m_NavMeshLayer: 0 31 | m_StaticEditorFlags: 0 32 | m_IsActive: 1 33 | --- !u!4 &4608705280554932 34 | Transform: 35 | m_ObjectHideFlags: 1 36 | m_PrefabParentObject: {fileID: 0} 37 | m_PrefabInternal: {fileID: 100100000} 38 | m_GameObject: {fileID: 1856826850138188} 39 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 40 | m_LocalPosition: {x: 0, y: 0.29999995, z: 0} 41 | m_LocalScale: {x: 1, y: 1, z: 1} 42 | m_Children: [] 43 | m_Father: {fileID: 0} 44 | m_RootOrder: 0 45 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 46 | --- !u!23 &23659821880543676 47 | MeshRenderer: 48 | m_ObjectHideFlags: 1 49 | m_PrefabParentObject: {fileID: 0} 50 | m_PrefabInternal: {fileID: 100100000} 51 | m_GameObject: {fileID: 1856826850138188} 52 | m_Enabled: 1 53 | m_CastShadows: 1 54 | m_ReceiveShadows: 1 55 | m_MotionVectors: 1 56 | m_LightProbeUsage: 1 57 | m_ReflectionProbeUsage: 1 58 | m_Materials: 59 | - {fileID: 2100000, guid: dddbdc46c2ca042d988c5981008d110c, type: 2} 60 | m_StaticBatchInfo: 61 | firstSubMesh: 0 62 | subMeshCount: 0 63 | m_StaticBatchRoot: {fileID: 0} 64 | m_ProbeAnchor: {fileID: 0} 65 | m_LightProbeVolumeOverride: {fileID: 0} 66 | m_ScaleInLightmap: 1 67 | m_PreserveUVs: 0 68 | m_IgnoreNormalsForChartDetection: 0 69 | m_ImportantGI: 0 70 | m_SelectedEditorRenderState: 3 71 | m_MinimumChartSize: 4 72 | m_AutoUVMaxDistance: 0.5 73 | m_AutoUVMaxAngle: 89 74 | m_LightmapParameters: {fileID: 0} 75 | m_SortingLayerID: 0 76 | m_SortingLayer: 0 77 | m_SortingOrder: 0 78 | --- !u!33 &33019469920901372 79 | MeshFilter: 80 | m_ObjectHideFlags: 1 81 | m_PrefabParentObject: {fileID: 0} 82 | m_PrefabInternal: {fileID: 100100000} 83 | m_GameObject: {fileID: 1856826850138188} 84 | m_Mesh: {fileID: 0} 85 | --- !u!114 &114820971152666198 86 | MonoBehaviour: 87 | m_ObjectHideFlags: 1 88 | m_PrefabParentObject: {fileID: 0} 89 | m_PrefabInternal: {fileID: 100100000} 90 | m_GameObject: {fileID: 1856826850138188} 91 | m_Enabled: 1 92 | m_EditorHideFlags: 0 93 | m_Script: {fileID: 11500000, guid: fade3408622cc489389f11fa87ef789f, type: 3} 94 | m_Name: 95 | m_EditorClassIdentifier: 96 | --- !u!114 &114952813105359896 97 | MonoBehaviour: 98 | m_ObjectHideFlags: 1 99 | m_PrefabParentObject: {fileID: 0} 100 | m_PrefabInternal: {fileID: 100100000} 101 | m_GameObject: {fileID: 1856826850138188} 102 | m_Enabled: 1 103 | m_EditorHideFlags: 0 104 | m_Script: {fileID: 11500000, guid: 2887d9e1347224887b4884ed8460a654, type: 3} 105 | m_Name: 106 | m_EditorClassIdentifier: 107 | data: 108 | randomSeed: 1 109 | lengthAttenuation: 0.856 110 | radiusAttenuation: 0.537 111 | branchesMin: 2 112 | branchesMax: 3 113 | growthAngleMin: -17.7 114 | growthAngleMax: 18.4 115 | growthAngleScale: 4 116 | heightSegments: 10 117 | radialSegments: 8 118 | bendDegree: 0.2 119 | generations: 5 120 | length: 1.25 121 | radius: 0.18 122 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Demo/ProceduralTree.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1176b6e8bdb4243c89985522eca2e63e 3 | timeCreated: 1505887537 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a40234d3faadf5f4fb2d914d641c66e2 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/Ground.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_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Ground 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.644 64 | - _GlossyReflections: 1 65 | - _Height: 0.1 66 | - _Metallic: 0.259 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 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/Ground.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f0225ce3e4e448cbb90bd96eeabfd50 3 | timeCreated: 1505885838 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeNormal.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_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ProceduralTreeNormal 10 | m_Shader: {fileID: 4800000, guid: c0927337b13cf4b29a587d50bf94ddc8, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _T: 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 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeNormal.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ca5d3ed8d95b47e4aed998976ea76a9 3 | timeCreated: 1505878968 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeStandard.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_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ProceduralTreeStandard 10 | m_Shader: {fileID: 4800000, guid: 21fe5bc6468874ac29841fabfe5566b6, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: ec662f3f8012c56448e2f19f2f20fbd5, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _T: 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 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeStandard.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dddbdc46c2ca042d988c5981008d110c 3 | timeCreated: 1505878968 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeUV.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_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ProceduralTreeUV 10 | m_Shader: {fileID: 4800000, guid: 9a40e3580206b4be28749e2bc3a0d495, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _T: 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 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Materials/ProceduralTreeUV.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 07b5408875ec940efbf0ecdb26d0c942 3 | timeCreated: 1505878968 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f0383319cecf3fd4b8ccfde957a09e2a 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9898a25bf8f3f47e89f48a7e0d7dd2f5 3 | folderAsset: yes 4 | timeCreated: 1505885035 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CatmullRomCurve.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 0} 8 | m_GameObject: {fileID: 0} 9 | m_Enabled: 1 10 | m_EditorHideFlags: 0 11 | m_Script: {fileID: 0} 12 | m_Name: CatmullRomCurve 13 | m_EditorClassIdentifier: Assembly-CSharp:ProceduralModeling:CatmullRomCurve 14 | points: 15 | - {x: 0, y: 0, z: 0} 16 | - {x: 1, y: 0, z: 0} 17 | - {x: 0, y: 1, z: 0} 18 | - {x: -1, y: 0, z: 0} 19 | closed: 0 20 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CatmullRomCurve.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8070884943c914a19a65361f39e22175 3 | timeCreated: 1505804880 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 11400000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CatmullRomCurve.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace ProceduralModeling { 6 | 7 | public class CubicPoly3D { 8 | Vector3 c0, c1, c2, c3; 9 | 10 | public CubicPoly3D(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, float tension = 0.5f) { 11 | var t0 = tension * (v2 - v0); 12 | var t1 = tension * (v3 - v1); 13 | 14 | c0 = v1; 15 | c1 = t0; 16 | c2 = -3f * v1 + 3f * v2 - 2f * t0 - t1; 17 | c3 = 2f * v1 - 2f * v2 + t0 + t1; 18 | } 19 | 20 | public Vector3 Calculate(float t) { 21 | var t2 = t * t; 22 | var t3 = t2 * t; 23 | return c0 + c1 * t + c2 * t2 + c3 * t3; 24 | } 25 | } 26 | 27 | public class CatmullRomCurve : CurveBase { 28 | 29 | public CatmullRomCurve(List points, bool closed = false) : base(points, closed) {} 30 | 31 | protected override Vector3 GetPoint(float t) { 32 | var points = this.points; 33 | var l = points.Count; 34 | 35 | var point = (l - (this.closed ? 0 : 1)) * t; 36 | var intPoint = Mathf.FloorToInt(point); 37 | var weight = point - intPoint; 38 | 39 | if (this.closed) { 40 | intPoint += intPoint > 0 ? 0 : (Mathf.FloorToInt(Mathf.Abs(intPoint) / points.Count) + 1) * points.Count; 41 | } else if (weight == 0 && intPoint == l - 1) { 42 | intPoint = l - 2; 43 | weight = 1; 44 | } 45 | 46 | Vector3 tmp, p0, p1, p2, p3; // 4 points 47 | if (this.closed || intPoint > 0) { 48 | p0 = points[(intPoint - 1) % l]; 49 | } else { 50 | // extrapolate first point 51 | tmp = (points[0] - points[1]) + points[0]; 52 | p0 = tmp; 53 | } 54 | 55 | p1 = points[intPoint % l]; 56 | p2 = points[(intPoint + 1) % l]; 57 | 58 | if (this.closed || intPoint + 2 < l) { 59 | p3 = points[(intPoint + 2) % l]; 60 | } else { 61 | // extrapolate last point 62 | tmp = (points[l - 1] - points[l - 2]) + points[l - 1]; 63 | p3 = tmp; 64 | } 65 | 66 | var poly = new CubicPoly3D(p0, p1, p2, p3); 67 | return poly.Calculate(weight); 68 | } 69 | } 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CatmullRomCurve.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9c23c2c16758462fb366990965ca08a 3 | timeCreated: 1505712122 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CurveBase.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using UnityEngine; 6 | 7 | namespace ProceduralModeling { 8 | 9 | public abstract class CurveBase { 10 | 11 | public List Points { get { return points; } } 12 | 13 | [SerializeField] protected List points = new List() { Vector3.zero, Vector3.right, Vector3.up, Vector3.left }; 14 | [SerializeField] protected bool closed = false; 15 | 16 | protected float[] cacheArcLengths; 17 | bool needsUpdate; 18 | 19 | public CurveBase(List points, bool closed = false) { 20 | this.points = points; 21 | this.closed = closed; 22 | } 23 | 24 | protected abstract Vector3 GetPoint(float t); 25 | 26 | protected virtual Vector3 GetTangent(float t) { 27 | var delta = 0.001f; 28 | var t1 = t - delta; 29 | var t2 = t + delta; 30 | 31 | // Capping in case of danger 32 | if (t1 < 0f) t1 = 0f; 33 | if (t2 > 1f) t2 = 1f; 34 | 35 | var pt1 = GetPoint(t1); 36 | var pt2 = GetPoint(t2); 37 | return (pt2 - pt1).normalized; 38 | } 39 | 40 | public Vector3 GetPointAt(float u) { 41 | float t = GetUtoTmapping(u); 42 | return GetPoint(t); 43 | } 44 | 45 | public Vector3 GetTangentAt(float u) { 46 | float t = GetUtoTmapping(u); 47 | return GetTangent(t); 48 | } 49 | 50 | float[] GetLengths(int divisions = -1) { 51 | if (divisions < 0) { 52 | divisions = 200; 53 | } 54 | 55 | if (this.cacheArcLengths != null && 56 | (this.cacheArcLengths.Length == divisions + 1) && 57 | !this.needsUpdate) { 58 | return this.cacheArcLengths; 59 | } 60 | 61 | this.needsUpdate = false; 62 | 63 | var cache = new float[divisions + 1]; 64 | Vector3 current, last = this.GetPoint(0f); 65 | 66 | cache[0] = 0f; 67 | 68 | float sum = 0f; 69 | for (int p = 1; p <= divisions; p ++ ) { 70 | current = this.GetPoint(1f * p / divisions); 71 | sum += Vector3.Distance(current, last); 72 | cache[p] = sum; 73 | last = current; 74 | } 75 | 76 | this.cacheArcLengths = cache; 77 | return cache; 78 | } 79 | 80 | protected float GetUtoTmapping(float u) { 81 | var arcLengths = this.GetLengths(); 82 | 83 | int i = 0, il = arcLengths.Length; 84 | 85 | float targetArcLength = u * arcLengths[il - 1]; 86 | 87 | int low = 0, high = il - 1; 88 | float comparison; 89 | 90 | while ( low <= high ) { 91 | 92 | i = Mathf.FloorToInt(low + (high - low) / 2f); 93 | comparison = arcLengths[i] - targetArcLength; 94 | 95 | if (comparison < 0f) { 96 | low = i + 1; 97 | } else if (comparison > 0f) { 98 | high = i - 1; 99 | } else { 100 | high = i; 101 | break; 102 | } 103 | 104 | } 105 | 106 | i = high; 107 | 108 | if (Mathf.Approximately(arcLengths[i], targetArcLength)) { 109 | return 1f * i / ( il - 1 ); 110 | } 111 | 112 | var lengthBefore = arcLengths[i]; 113 | var lengthAfter = arcLengths[i + 1]; 114 | 115 | var segmentLength = lengthAfter - lengthBefore; 116 | 117 | var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 118 | 119 | var t = 1f * (i + segmentFraction) / (il - 1); 120 | 121 | return t; 122 | } 123 | 124 | public List ComputeFrenetFrames (int segments, bool closed = false) { 125 | var tangent = GetTangentAt(0f).normalized; 126 | var tx = Mathf.Abs(tangent.x); 127 | var ty = Mathf.Abs(tangent.y); 128 | var tz = Mathf.Abs(tangent.z); 129 | 130 | var normal = new Vector3(); 131 | var min = float.MaxValue; 132 | if (tx <= min) { 133 | min = tx; 134 | normal.Set(1, 0, 0); 135 | } 136 | if (ty <= min) { 137 | min = ty; 138 | normal.Set(0, 1, 0); 139 | } 140 | if (tz <= min) { 141 | normal.Set(0, 0, 1); 142 | } 143 | 144 | var vec = Vector3.Cross(tangent, normal).normalized; 145 | normal = Vector3.Cross(tangent, vec); 146 | var binormal = Vector3.Cross(tangent, normal); 147 | return ComputeFrenetFrames(segments, normal, binormal, closed); 148 | } 149 | 150 | public List ComputeFrenetFrames(int segments, Vector3 normal, Vector3 binormal, bool closed = false) { 151 | var tangents = new Vector3[segments + 1]; 152 | var normals = new Vector3[segments + 1]; 153 | var binormals = new Vector3[segments + 1]; 154 | 155 | for (int i = 0; i <= segments; i++) { 156 | var u = (1f * i) / segments; 157 | tangents[i] = GetTangentAt(u).normalized; 158 | } 159 | 160 | normals[0] = normal; 161 | binormals[0] = binormal; 162 | 163 | float theta; 164 | 165 | for (int i = 1; i <= segments; i++) { 166 | // copy previous 167 | normals[i] = normals[i - 1]; 168 | binormals[i] = binormals[i - 1]; 169 | 170 | var axis = Vector3.Cross(tangents[i - 1], tangents[i]); 171 | if (axis.magnitude > float.Epsilon) { 172 | axis.Normalize(); 173 | 174 | float dot = Vector3.Dot(tangents[i - 1], tangents[i]); 175 | 176 | theta = Mathf.Acos(Mathf.Clamp(dot, -1f, 1f)); 177 | 178 | normals[i] = Quaternion.AngleAxis(theta * Mathf.Rad2Deg, axis) * normals[i]; 179 | } 180 | 181 | binormals[i] = Vector3.Cross(tangents[i], normals[i]).normalized; 182 | } 183 | 184 | if (closed) { 185 | theta = Mathf.Acos(Mathf.Clamp(Vector3.Dot(normals[0], normals[segments]), -1f, 1f)); 186 | theta /= segments; 187 | 188 | if (Vector3.Dot(tangents[0], Vector3.Cross(normals[0], normals[segments])) > 0f) { 189 | theta = - theta; 190 | } 191 | 192 | for (int i = 1; i <= segments; i++) { 193 | normals[i] = (Quaternion.AngleAxis(Mathf.Deg2Rad * theta * i, tangents[i]) * normals[i]); 194 | binormals[i] = Vector3.Cross(tangents[i], normals[i]); 195 | } 196 | } 197 | 198 | var frames = new List(); 199 | int n = tangents.Length; 200 | for(int i = 0; i < n; i++) { 201 | var frame = new FrenetFrame(tangents[i], normals[i], binormals[i]); 202 | frames.Add(frame); 203 | } 204 | return frames; 205 | } 206 | 207 | } 208 | 209 | } 210 | 211 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/CurveBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 595e7e825ee1e46b8843d84f8e9e00a2 3 | timeCreated: 1505713999 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/FrenetFrame.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace ProceduralModeling { 6 | 7 | public class FrenetFrame { 8 | public Vector3 Tangent { get { return tangent; } } 9 | public Vector3 Normal { get { return normal; } } 10 | public Vector3 Binormal { get { return binormal; } } 11 | 12 | Vector3 tangent, normal, binormal; 13 | 14 | public FrenetFrame(Vector3 t, Vector3 n, Vector3 bn) { 15 | tangent = t; 16 | normal = n; 17 | binormal = bn; 18 | } 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Curve/FrenetFrame.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8ff12b974d30349d092853eef6b216f5 3 | timeCreated: 1505712115 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b97f434b1e4474b43a3ef2b3f8d36b15 3 | folderAsset: yes 4 | timeCreated: 1505885035 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Editor/ProceduralModelingEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | using UnityEngine; 5 | using UnityEditor; 6 | 7 | namespace ProceduralModeling { 8 | 9 | [CustomEditor (typeof(ProceduralModelingBase), true)] 10 | public class ProceduralModelingEditor : Editor { 11 | 12 | public override void OnInspectorGUI() { 13 | EditorGUI.BeginChangeCheck(); 14 | base.OnInspectorGUI(); 15 | if(EditorGUI.EndChangeCheck()) { 16 | var pm = target as ProceduralModelingBase; 17 | pm.Rebuild(); 18 | } 19 | } 20 | 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/Editor/ProceduralModelingEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 832fe1a7522da45c898c37662ea684c4 3 | timeCreated: 1505884548 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/ProceduralModelingBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace ProceduralModeling { 6 | 7 | [RequireComponent (typeof(MeshFilter), typeof(MeshRenderer))] 8 | [ExecuteInEditMode] 9 | public abstract class ProceduralModelingBase : MonoBehaviour { 10 | 11 | public MeshFilter Filter { 12 | get { 13 | if(filter == null) { 14 | filter = GetComponent(); 15 | } 16 | return filter; 17 | } 18 | } 19 | 20 | MeshFilter filter; 21 | 22 | protected virtual void Start () { 23 | Rebuild(); 24 | } 25 | 26 | public void Rebuild() { 27 | if(Filter.sharedMesh != null) { 28 | if(Application.isPlaying) { 29 | Destroy(Filter.sharedMesh); 30 | } else { 31 | DestroyImmediate(Filter.sharedMesh); 32 | } 33 | } 34 | Filter.sharedMesh = Build(); 35 | } 36 | 37 | protected abstract Mesh Build(); 38 | 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/ProceduralModelingBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: adb1484883e9f472696c49705d507146 3 | timeCreated: 1505885066 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/ProceduralTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | 6 | using UnityEngine; 7 | 8 | namespace ProceduralModeling { 9 | 10 | public class ProceduralTree : ProceduralModelingBase { 11 | 12 | public TreeData Data { get { return data; } } 13 | 14 | [SerializeField] TreeData data; 15 | [SerializeField, Range(2, 8)] protected int generations = 5; 16 | [SerializeField, Range(0.5f, 5f)] protected float length = 1f; 17 | [SerializeField, Range(0.1f, 2f)] protected float radius = 0.15f; 18 | 19 | const float PI2 = Mathf.PI * 2f; 20 | 21 | public static Mesh Build(TreeData data, int generations, float length, float radius) { 22 | data.Setup(); 23 | 24 | var root = new TreeBranch( 25 | generations, 26 | length, 27 | radius, 28 | data 29 | ); 30 | 31 | var vertices = new List(); 32 | var normals = new List(); 33 | var tangents = new List(); 34 | var uvs = new List(); 35 | var triangles = new List(); 36 | 37 | float maxLength = TraverseMaxLength(root); 38 | 39 | Traverse(root, (branch) => { 40 | var offset = vertices.Count; 41 | 42 | var vOffset = branch.Offset / maxLength; 43 | var vLength = branch.Length / maxLength; 44 | 45 | for(int i = 0, n = branch.Segments.Count; i < n; i++) { 46 | var t = 1f * i / (n - 1); 47 | var v = vOffset + vLength * t; 48 | 49 | var segment = branch.Segments[i]; 50 | var N = segment.Frame.Normal; 51 | var B = segment.Frame.Binormal; 52 | for(int j = 0; j <= data.radialSegments; j++) { 53 | // 0.0 ~ 2π 54 | var u = 1f * j / data.radialSegments; 55 | float rad = u * PI2; 56 | 57 | float cos = Mathf.Cos(rad), sin = Mathf.Sin(rad); 58 | var normal = (cos * N + sin * B).normalized; 59 | vertices.Add(segment.Position + segment.Radius * normal); 60 | normals.Add(normal); 61 | 62 | var tangent = segment.Frame.Tangent; 63 | tangents.Add(new Vector4(tangent.x, tangent.y, tangent.z, 0f)); 64 | 65 | uvs.Add(new Vector2(u, v)); 66 | } 67 | } 68 | 69 | for (int j = 1; j <= data.heightSegments; j++) { 70 | for (int i = 1; i <= data.radialSegments; i++) { 71 | int a = (data.radialSegments + 1) * (j - 1) + (i - 1); 72 | int b = (data.radialSegments + 1) * j + (i - 1); 73 | int c = (data.radialSegments + 1) * j + i; 74 | int d = (data.radialSegments + 1) * (j - 1) + i; 75 | 76 | a += offset; 77 | b += offset; 78 | c += offset; 79 | d += offset; 80 | 81 | triangles.Add(a); triangles.Add(d); triangles.Add(b); 82 | triangles.Add(b); triangles.Add(d); triangles.Add(c); 83 | } 84 | } 85 | }); 86 | 87 | var mesh = new Mesh(); 88 | mesh.vertices = vertices.ToArray(); 89 | mesh.normals = normals.ToArray(); 90 | mesh.tangents = tangents.ToArray(); 91 | mesh.uv = uvs.ToArray(); 92 | mesh.triangles = triangles.ToArray(); 93 | return mesh; 94 | } 95 | 96 | protected override Mesh Build () 97 | { 98 | return Build(data, generations, length, radius); 99 | } 100 | 101 | static float TraverseMaxLength(TreeBranch branch) { 102 | float max = 0f; 103 | branch.Children.ForEach(c => { 104 | max = Mathf.Max(max, TraverseMaxLength(c)); 105 | }); 106 | return branch.Length + max; 107 | } 108 | 109 | static void Traverse(TreeBranch from, Action action) { 110 | if(from.Children.Count > 0) { 111 | from.Children.ForEach(child => { 112 | Traverse(child, action); 113 | }); 114 | } 115 | action(from); 116 | } 117 | 118 | } 119 | 120 | [System.Serializable] 121 | public class TreeData { 122 | public int randomSeed = 0; 123 | [Range(0.25f, 0.95f)] public float lengthAttenuation = 0.8f, radiusAttenuation = 0.5f; 124 | [Range(1, 3)] public int branchesMin = 1, branchesMax = 3; 125 | [Range(-45f, 0f)] public float growthAngleMin = -15f; 126 | [Range(0f, 45f)] public float growthAngleMax = 15f; 127 | [Range(1f, 10f)] public float growthAngleScale = 4f; 128 | [Range(4, 20)] public int heightSegments = 10, radialSegments = 8; 129 | [Range(0.0f, 0.35f)] public float bendDegree = 0.1f; 130 | 131 | Rand rnd; 132 | 133 | public void Setup() { 134 | rnd = new Rand(randomSeed); 135 | } 136 | 137 | public int Range(int a, int b) { 138 | return rnd.Range(a, b); 139 | } 140 | 141 | public float Range(float a, float b) { 142 | return rnd.Range(a, b); 143 | } 144 | 145 | public int GetRandomBranches() { 146 | return rnd.Range(branchesMin, branchesMax + 1); 147 | } 148 | 149 | public float GetRandomGrowthAngle() { 150 | return rnd.Range(growthAngleMin, growthAngleMax); 151 | } 152 | 153 | public float GetRandomBendDegree() { 154 | return rnd.Range(-bendDegree, bendDegree); 155 | } 156 | } 157 | 158 | public class TreeBranch { 159 | public int Generation { get { return generation; } } 160 | public List Segments { get { return segments; } } 161 | public List Children { get { return children; } } 162 | 163 | public Vector3 From { get { return from; } } 164 | public Vector3 To { get { return to; } } 165 | public float Length { get { return length; } } 166 | public float Offset { get { return offset; } } 167 | 168 | int generation; 169 | 170 | List segments; 171 | List children; 172 | 173 | Vector3 from, to; 174 | float fromRadius, toRadius; 175 | float length; 176 | float offset; 177 | 178 | // for Root branch constructor 179 | public TreeBranch(int generation, float length, float radius, TreeData data) : this(new List(), generation, generation, Vector3.zero, Vector3.up, Vector3.right, Vector3.back, length, radius, 0f, data) { 180 | } 181 | 182 | protected TreeBranch(List branches, int generation, int generations, Vector3 from, Vector3 tangent, Vector3 normal, Vector3 binormal, float length, float radius, float offset, TreeData data) { 183 | this.generation = generation; 184 | 185 | this.fromRadius = radius; 186 | this.toRadius = (generation == 0) ? 0f : radius * data.radiusAttenuation; 187 | 188 | this.from = from; 189 | 190 | var scale = Mathf.Lerp(1f, data.growthAngleScale, 1f - 1f * generation / generations); 191 | var rotation = Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), normal) * Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), binormal); 192 | this.to = from + rotation * tangent * length; 193 | 194 | this.length = length; 195 | this.offset = offset; 196 | 197 | segments = BuildSegments(data, fromRadius, toRadius, normal, binormal); 198 | 199 | branches.Add(this); 200 | 201 | children = new List(); 202 | if(generation > 0) { 203 | int count = data.GetRandomBranches(); 204 | for(int i = 0; i < count; i++) { 205 | float ratio; 206 | if(count == 1) 207 | { 208 | // for zero division 209 | ratio = 1f; 210 | } else 211 | { 212 | ratio = Mathf.Lerp(0.5f, 1f, (1f * i) / (count - 1)); 213 | } 214 | 215 | var index = Mathf.FloorToInt(ratio * (segments.Count - 1)); 216 | var segment = segments[index]; 217 | 218 | Vector3 nt, nn, nb; 219 | if(ratio >= 1f) 220 | { 221 | // sequence branch 222 | nt = segment.Frame.Tangent; 223 | nn = segment.Frame.Normal; 224 | nb = segment.Frame.Binormal; 225 | } else 226 | { 227 | var rot = Quaternion.AngleAxis(i * 90f, tangent); 228 | nt = rot * tangent; 229 | nn = rot * normal; 230 | nb = rot * binormal; 231 | } 232 | 233 | var child = new TreeBranch( 234 | branches, 235 | this.generation - 1, 236 | generations, 237 | segment.Position, 238 | nt, 239 | nn, 240 | nb, 241 | length * Mathf.Lerp(1f, data.lengthAttenuation, ratio), 242 | radius * Mathf.Lerp(1f, data.radiusAttenuation, ratio), 243 | offset + length, 244 | data 245 | ); 246 | 247 | children.Add(child); 248 | } 249 | } 250 | } 251 | 252 | List BuildSegments (TreeData data, float fromRadius, float toRadius, Vector3 normal, Vector3 binormal) { 253 | var segments = new List(); 254 | 255 | var points = new List(); 256 | 257 | var length = (to - from).magnitude; 258 | var bend = length * (normal * data.GetRandomBendDegree() + binormal * data.GetRandomBendDegree()); 259 | points.Add(from); 260 | points.Add(Vector3.Lerp(from, to, 0.25f) + bend); 261 | points.Add(Vector3.Lerp(from, to, 0.75f) + bend); 262 | points.Add(to); 263 | 264 | var curve = new CatmullRomCurve(points); 265 | 266 | var frames = curve.ComputeFrenetFrames(data.heightSegments, normal, binormal, false); 267 | for(int i = 0, n = frames.Count; i < n; i++) { 268 | var u = 1f * i / (n - 1); 269 | var radius = Mathf.Lerp(fromRadius, toRadius, u); 270 | 271 | var position = curve.GetPointAt(u); 272 | var segment = new TreeSegment(frames[i], position, radius); 273 | segments.Add(segment); 274 | } 275 | return segments; 276 | } 277 | 278 | } 279 | 280 | public class TreeSegment { 281 | public FrenetFrame Frame { get { return frame; } } 282 | public Vector3 Position { get { return position; } } 283 | public float Radius { get { return radius; } } 284 | 285 | FrenetFrame frame; 286 | Vector3 position; 287 | float radius; 288 | 289 | public TreeSegment(FrenetFrame frame, Vector3 position, float radius) { 290 | this.frame = frame; 291 | this.position = position; 292 | this.radius = radius; 293 | } 294 | } 295 | 296 | public class Rand { 297 | System.Random rnd; 298 | 299 | public float value { 300 | get { 301 | return (float)rnd.NextDouble(); 302 | } 303 | } 304 | 305 | public Rand(int seed) { 306 | rnd = new System.Random(seed); 307 | } 308 | 309 | public int Range(int a, int b) { 310 | var v = value; 311 | return Mathf.FloorToInt(Mathf.Lerp(a, b, v)); 312 | } 313 | 314 | public float Range(float a, float b) { 315 | var v = value; 316 | return Mathf.Lerp(a, b, v); 317 | } 318 | } 319 | 320 | } 321 | 322 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Scripts/ProceduralTree.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2887d9e1347224887b4884ed8460a654 3 | timeCreated: 1505885036 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 121b668a1c2851d41b38cc2c567257fa 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTree.cginc: -------------------------------------------------------------------------------- 1 | #ifndef _PROCEDURAL_TREE_COMMON_ 2 | #define _PROCEDURAL_TREE_COMMON_ 3 | 4 | fixed _T; 5 | 6 | void procedural_tree_clip(float2 uv) { 7 | clip(_T - uv.y); 8 | } 9 | 10 | #endif -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTree.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 694781d8f08c946438e85fb3a5d74aa6 3 | timeCreated: 1505879194 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeNormal.shader: -------------------------------------------------------------------------------- 1 | Shader "ProceduralModeling/ProceduralTreeNormal" 2 | { 3 | Properties 4 | { 5 | _T ("Growing", Range(0.0, 1.0)) = 1.0 6 | } 7 | SubShader 8 | { 9 | Tags { "RenderType"="Opaque" } 10 | LOD 100 11 | 12 | Pass 13 | { 14 | CGPROGRAM 15 | #pragma vertex vert 16 | #pragma fragment frag 17 | 18 | #include "UnityCG.cginc" 19 | #include "./ProceduralTree.cginc" 20 | 21 | struct appdata 22 | { 23 | float4 vertex : POSITION; 24 | float2 uv : TEXCOORD0; 25 | float3 normal : NORMAL; 26 | }; 27 | 28 | struct v2f 29 | { 30 | float4 vertex : SV_POSITION; 31 | float2 uv : TEXCOORD0; 32 | float3 normal : NORMAL; 33 | }; 34 | 35 | v2f vert (appdata v) 36 | { 37 | v2f o; 38 | o.vertex = UnityObjectToClipPos(v.vertex); 39 | o.uv = v.uv; 40 | o.normal = v.normal; 41 | return o; 42 | } 43 | 44 | fixed4 frag (v2f i) : SV_Target 45 | { 46 | procedural_tree_clip(i.uv); 47 | return fixed4((i.normal + 1.0) * 0.5, 1.0); 48 | } 49 | ENDCG 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeNormal.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c0927337b13cf4b29a587d50bf94ddc8 3 | timeCreated: 1505879393 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeStandard.shader: -------------------------------------------------------------------------------- 1 | Shader "ProceduralModeling/ProceduralTreeStandard" { 2 | Properties { 3 | _Color ("Color", Color) = (1,1,1,1) 4 | _MainTex ("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness ("Smoothness", Range(0,1)) = 0.5 6 | _Metallic ("Metallic", Range(0,1)) = 0.0 7 | 8 | _T ("Growing", Range(0.0, 1.0)) = 1.0 9 | } 10 | SubShader { 11 | Tags { "RenderType"="Opaque" } 12 | LOD 200 13 | 14 | CGPROGRAM 15 | #pragma surface surf Standard vertex:vert addshadow 16 | 17 | #pragma target 3.0 18 | 19 | #include "UnityCG.cginc" 20 | #include "./ProceduralTree.cginc" 21 | 22 | sampler2D _MainTex; 23 | 24 | struct Input { 25 | float2 uv_MainTex; 26 | float2 texcoord; 27 | }; 28 | 29 | half _Glossiness; 30 | half _Metallic; 31 | fixed4 _Color; 32 | 33 | void vert(inout appdata_full v, out Input o) { 34 | UNITY_INITIALIZE_OUTPUT(Input, o); 35 | o.texcoord = v.texcoord; 36 | } 37 | 38 | void surf (Input IN, inout SurfaceOutputStandard o) { 39 | procedural_tree_clip(IN.texcoord); 40 | fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 41 | o.Albedo = c.rgb; 42 | o.Metallic = _Metallic; 43 | o.Smoothness = _Glossiness; 44 | o.Alpha = c.a; 45 | } 46 | 47 | ENDCG 48 | } 49 | FallBack "Diffuse" 50 | } 51 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeStandard.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21fe5bc6468874ac29841fabfe5566b6 3 | timeCreated: 1505878950 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeUV.shader: -------------------------------------------------------------------------------- 1 | Shader "ProceduralModeling/ProceduralTreeUV" 2 | { 3 | Properties 4 | { 5 | _T ("Growing", Range(0.0, 1.0)) = 1.0 6 | } 7 | SubShader 8 | { 9 | Tags { "RenderType"="Opaque" } 10 | LOD 100 11 | 12 | Pass 13 | { 14 | CGPROGRAM 15 | #pragma vertex vert 16 | #pragma fragment frag 17 | 18 | #include "UnityCG.cginc" 19 | #include "./ProceduralTree.cginc" 20 | 21 | struct appdata 22 | { 23 | float4 vertex : POSITION; 24 | float2 uv : TEXCOORD0; 25 | }; 26 | 27 | struct v2f 28 | { 29 | float4 vertex : SV_POSITION; 30 | float2 uv : TEXCOORD0; 31 | }; 32 | 33 | v2f vert (appdata v) 34 | { 35 | v2f o; 36 | o.vertex = UnityObjectToClipPos(v.vertex); 37 | o.uv = v.uv; 38 | return o; 39 | } 40 | 41 | fixed4 frag (v2f i) : SV_Target 42 | { 43 | procedural_tree_clip(i.uv); 44 | return fixed4(i.uv, 0, 1.0); 45 | } 46 | ENDCG 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Shaders/ProceduralTreeUV.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a40e3580206b4be28749e2bc3a0d495 3 | timeCreated: 1505879393 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9d1bda2e3dc7d248b856149bc83ce1e 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Textures/Tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattatz/unity-procedural-tree/05374e1d9f8a2b24d58f78b319248922d52bc6db/Assets/Packages/ProceduralTree/Textures/Tree.jpg -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Textures/Tree.jpg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec662f3f8012c56448e2f19f2f20fbd5 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 0 42 | textureType: -1 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Textures/UVTextureChecker4096.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattatz/unity-procedural-tree/05374e1d9f8a2b24d58f78b319248922d52bc6db/Assets/Packages/ProceduralTree/Textures/UVTextureChecker4096.png -------------------------------------------------------------------------------- /Assets/Packages/ProceduralTree/Textures/UVTextureChecker4096.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 156f2f491e07f614ea19c9b649ebb193 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | seamlessCubemap: 0 24 | textureFormat: -1 25 | maxTextureSize: 1024 26 | textureSettings: 27 | filterMode: -1 28 | aniso: -1 29 | mipBias: -1 30 | wrapMode: -1 31 | nPOTScale: 1 32 | lightmap: 0 33 | compressionQuality: 50 34 | spriteMode: 0 35 | spriteExtrude: 1 36 | spriteMeshType: 1 37 | alignment: 0 38 | spritePivot: {x: .5, y: .5} 39 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 40 | spritePixelsToUnits: 100 41 | alphaIsTransparency: 0 42 | textureType: -1 43 | buildTargetSettings: [] 44 | spriteSheet: 45 | sprites: [] 46 | spritePackingTag: 47 | userData: 48 | -------------------------------------------------------------------------------- /Captures/Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattatz/unity-procedural-tree/05374e1d9f8a2b24d58f78b319248922d52bc6db/Captures/Demo.gif -------------------------------------------------------------------------------- /Captures/TreeData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattatz/unity-procedural-tree/05374e1d9f8a2b24d58f78b319248922d52bc6db/Captures/TreeData.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 mattatz 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 | -------------------------------------------------------------------------------- /ProceduralTree.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattatz/unity-procedural-tree/05374e1d9f8a2b24d58f78b319248922d52bc6db/ProceduralTree.unitypackage -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | unity-procedural-tree 2 | ===================== 3 | 4 | Procedural tree builder for Unity. 5 | 6 | ![Demo](https://raw.githubusercontent.com/mattatz/unity-procedural-tree/master/Captures/Demo.gif) 7 | 8 | ## Usage 9 | 10 | TreeData class has properties of ProceduralTree. 11 | 12 | ![TreeData](https://raw.githubusercontent.com/mattatz/unity-procedural-tree/master/Captures/TreeData.png) 13 | 14 | Setup a TreeData instance and pass it to ProceduralTree.Build function. 15 | 16 | ```cs 17 | // Setup TreeData for properties of ProceduralTree 18 | TreeData data = new TreeData(); 19 | // data.randomSeed = 100; 20 | // data.branchesMin = 1; data.branchesMax = 3; 21 | 22 | Mesh mesh = ProceduralTree.Build( 23 | data, 24 | 6, // generations of a tree 25 | 1.5f, // base height of a tree 26 | 0.15f // base radius of a tree 27 | ); 28 | ``` 29 | 30 | --------------------------------------------------------------------------------