Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by micahart · Apr 22 at 10:35 AM · rotationprocedural meshcylinder

Generating a procedural cylindrical mesh following a path

Hi,

I'm trying to procedurally generate meshes following paths generated by a space colonization algorithm. I am trying to do this by generating rings of vertices around each point in the path, and rotating them to face the previous point in the path (if it exists), which will hopefully produce cylindrical meshes following the path. However my code is producing some strange artifacts, especially as i increase the radius of the mesh generated. Because of this I think it may be due to the circles of vertices overlapping when they are rotated at increased radiuses, but I can't work out how to set minimum and maximum rotations for these circles based on the radius of the cylinder.

Any help or suggestions of alternative, better ways of producing similar results would be greatly appreciated as I'm sure this is far from the best way to go about it.

Here is the code responsible for taking a non-branching series of nodes and using their positions to generate the mesh, and some screenshots of the results.

          // function generate meshes from non-branching paths
         private Mesh[] GenerateMeshFromPaths(List<Node>[] inputPaths)
         {
             GameObject[] pathsToDelete = GameObject.FindGameObjectsWithTag("Mesh");
             foreach (GameObject pathToDelete in pathsToDelete)
             {
                 Destroy(pathToDelete);
             }
     
             // generate a ring of vertices around each node in each path
     
             // generate a mesh for each path
             Mesh[] pathMeshes = new Mesh[inputPaths.Length];
     
             // generate a 'stretch' containing important information about each mesh in the path
             stretches.Clear();
     
     
             // loop through paths
             for (int i = 0; i < inputPaths.Length; i++)
             {
                 pathMeshes[i] = new Mesh();
     
                 #region vertices
                 // loop through nodes in each path
                 List<Vector3> vertices = new List<Vector3>();
                 List<BoneWeight> boneWeights = new List<BoneWeight>();
     
                 vertices.Add(new Vector3(0, 0, 0) + inputPaths[i][0].position);
                 foreach (Node node in inputPaths[i])
                 { 
                     // get direction for ring to face
                     // https://answers.unity.com/questions/1744376/get-vertices-of-circle-facing-any-direction.html
     
                     Vector3 normal = Vector3.zero;
     
                     if (node.parent != null)
                     {
                         // if node has parent set parent node as direction to face
                         normal = (node.parent.position - node.position).normalized;
     
                     }
                     else if (node.child != null)
                     {
                         // if node has no parent but has child then face child
                         normal = (node.child.position - node.position).normalized;
                     }
                     else
                     {
                         // if node isolated then direction doesn't matter 
                     }
     
     
     
                     // return vector perpendicular to normal 
                     Vector3 tangent = Vector3.Cross(normal, (normal == Vector3.up) ? Vector3.forward : Vector3.up).normalized;
     
                     // loop over number of segments per node-ring
                     for (int j = 0; j < growthSettings.segments; j++)
                     {
                         float angle = j * 360f / growthSettings.segments;
     
                         float x = growthSettings.radius * Mathf.Cos(angle * Mathf.Deg2Rad) + node.position.x;
                         float y = growthSettings.radius * Mathf.Sin(angle * Mathf.Deg2Rad) + node.position.y;
                         // float z = node.position.z + growthSettings.segmentLength;
                         float z = node.position.z;
     
                         Vector3 rotatedVertex = node.position + (Quaternion.AngleAxis(j / (float)growthSettings.segments * 360f, normal) * tangent) * growthSettings.radius;
                         // Vector3 rotatedVertex = node.position + (Quaternion.AngleAxis((j / (float)growthSettings.segments) * 360f, normal) * tangent);
     
                         Vector3 newVertex = new Vector3(x, y, z);
     
                         vertices.Add(rotatedVertex);
                     }
                 }
                 vertices.Add(new Vector3(0, 0, 2f * growthSettings.radius + (growthSettings.segmentLength * inputPaths[i].Count)) + inputPaths[i][0].position);
                 pathMeshes[i].vertices = vertices.ToArray();
                 #endregion
     
                 #region triangles
                 List<int> triangles = new List<int>();
     
                 // loop over rings of vertices, adding triangle indexes
                 // for (int ring = 0; ring < inputPaths[i].Count-1; ring++)
                 for (int ring = 0; ring < (inputPaths[i].Count - 1); ring++)
                 {
                     int ringOffset = ring * growthSettings.segments;
                     // int ringOffset = 1 + ring * growthSettings.segments; 
     
                     // loop over segments
                     for (int j = 0; j < growthSettings.segments; j++)
                     {
                         int seamOffset = j != growthSettings.segments - 1 ? 0 : growthSettings.segments;
     
                         triangles.Add(ringOffset + j);
                         triangles.Add(ringOffset + j + 1 - seamOffset);
                         triangles.Add(ringOffset + j + 1 - seamOffset + growthSettings.segments);
     
                         triangles.Add(ringOffset + j + 1 - seamOffset + growthSettings.segments);
                         triangles.Add(ringOffset + j + growthSettings.segments);
                         triangles.Add(ringOffset + j);
                     }
     
                 }
     
                 pathMeshes[i].triangles = triangles.ToArray();
                 #endregion
     
                 NormalSolver.RecalculateNormals(pathMeshes[i], 0);
                 pathMeshes[i].RecalculateTangents(); 
     
                 #region UV
                 List<Vector2> uv = new List<Vector2>();
                 uv.Add(Vector3.zero);
                 for (int ring = 0; ring < (inputPaths[i].Count); ring++)
                 {
                     float v = ring / growthSettings.rings;
                     for (int k = 0; k < growthSettings.segments; k++)
                     {
                         float u = k / (float)(growthSettings.segments - 1);
                         uv.Add(new Vector2(u, v * (inputPaths[i].Count + 1)));
     
                         // uv.Add(new Vector2(0, 1)); 
                     }
     
                 }
                 uv.Add(Vector2.one);
                 pathMeshes[i].uv8 = uv.ToArray(); // Store copy of UVs in mesh.
                 pathMeshes[i].uv = uv.ToArray(); 
                 #endregion
                 //pathMeshes[i].SetUVs(0, pathMeshes[i].uv8);
     
     
     
     
             }
     
             for (int i = 0; i < pathMeshes.Length; i++)
             {
                 #region stretch 
     
                 // important information about path section held in stretch script
                 GameObject newStretch = Instantiate(stretchPrefab, transform);
                 newStretch.GetComponent<Stretch>().InitializeStretch(inputPaths[i][0], inputPaths[i][inputPaths[i].Count - 1], pathMeshes[i], meshMat);
                 //newStretch.GetComponent<Stretch>().SetStretch();
                 stretches.Add(newStretch);
                 #endregion
             }
     
             return pathMeshes;
         }


alt text

alt text

screen-shot-2022-04-21-at-112304.png (337.0 kB)
screen-shot-2022-04-21-at-112236.png (337.1 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by homer_3 · Apr 22 at 02:59 PM

I've found Tubular (https://github.com/mattatz/unity-tubular) to be great and very easy to use for this kind of thing.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image micahart · Apr 24 at 03:54 PM 0
Share

Hey, thanks so much for the answer, this looks extremely useful and likely to succeed. I just need to get a chance to have a go at implementing it before I accept the answer.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

181 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Variable height tile path on rotating disc/tube 0 Answers

Rotation math question: car movement on a cylinder 0 Answers

Cylinder object does not roll as intended 1 Answer

Dynamically change Vector3.up/right?,How to make a cylinder chase mechanic? 2 Answers

How to create a continuous link (growing cylinder) of instantiated models around a cylinder? (Vine growing up a tree) 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges