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 playsky · Jan 17 at 04:12 PM · meshspheresmoothprocedural mesh

How to get a smoothed Icosphere procedurally

Hello,

I'm making a planet generator and to build the sphere procedurally I decided to use an Icosphere because the triangles that compose it all have the same size which is I think the best option for this kind of project to after implement a level of detail system ( please tell me if I'm wrong and if there is a best solution )

So I followed this tutorial here to build the sphere, it works very well but I don't get a smooth sphere even with a lot of triangles.


For exemple here is the Icosphere with 5120 triangles which is a lot I think compare to unity sphere which is smooth for 760 triangles. I guess when I increase the number of triangles I get a better result but I don't think it's a good solution to have more than 100k triangles for a sphere which is not even smooth.

alt text


So is there a solution to smooth triangles or to simply have a smooth sphere like the unity sphere with an Icosphere ?

Thanks !

edit Copied from Answer:

I'm sorry I thought my code will be very too long to be posted. So here it is, I understand what you said and normally I normalize the points in the GetVertexToUnitSphere function in the Utility class which is called for each triangle instance, but I'm still learning the mesh system so I guess a part of my code could be wrong

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 [Serializable]
 public class CelestialShapeSettings
 {
     [Range(0, 10)]
     public int minDepth = 6;
     public float radius = 10;
     public NoiseLayer[] noiseLayers;
 }
 
 public class CelestialShape
 {
 
     CelestialShapeSettings settings;
 
     Mesh mesh;
 
     Vector3[] vertices;
     List<Triangle> triangles;
 
     NoiseFilter[] noiseFilters;
 
 
     public CelestialShape(Mesh mesh, CelestialShapeSettings settings)
     {
         this.mesh = mesh;
         this.settings = settings;
 
         noiseFilters = new NoiseFilter[settings.noiseLayers.Length];
         for (int i = 0; i < noiseFilters.Length; i++)
         {
             noiseFilters[i] = new NoiseFilter(settings.noiseLayers[i].settings);
         }
 
         SetupVertices();
     }
 
 
     private void SetupVertices()
     {
         if (vertices == null)
         {
             // goldenRatio
             float t = (1.0f + (float)Math.Sqrt(5.0)) / 2.0f;
 
             vertices = new Vector3[] {
                 // Trace the four vertices of a Golden rectangle [R1]
                 Utility.GetVertexToUnitSphere(new Vector3(-1, t, 0)),
                 Utility.GetVertexToUnitSphere(new Vector3(1, t, 0)),
                 Utility.GetVertexToUnitSphere(new Vector3(-1, -t, 0)),
                 Utility.GetVertexToUnitSphere(new Vector3(1, -t, 0)),
 
                 // Trace the four verices of a Golden rectangle orthagonal to the last [R2]
                 Utility.GetVertexToUnitSphere(new Vector3(0, -1, t)),
                 Utility.GetVertexToUnitSphere(new Vector3(0, 1, t)),
                 Utility.GetVertexToUnitSphere(new Vector3(0, -1, -t)),
                 Utility.GetVertexToUnitSphere(new Vector3(0, 1, -t)),
 
                 // Trace the four verices of a Golden rectangle orthagonal to the last two [R3]
                 Utility.GetVertexToUnitSphere(new Vector3(t, 0, -1)),
                 Utility.GetVertexToUnitSphere(new Vector3(t, 0, 1)),
                 Utility.GetVertexToUnitSphere(new Vector3(-t, 0, -1)),
                 Utility.GetVertexToUnitSphere(new Vector3(-t, 0, 1))
             };
         }
     }
 
     private void SetupTriangles()
     {
         triangles = new List<Triangle> {
             // 5 faces around point 0
             new Triangle(vertices[0], vertices[11], vertices[5]),
             new Triangle(vertices[0], vertices[5], vertices[1]),
             new Triangle(vertices[0], vertices[1], vertices[7]),
             new Triangle(vertices[0], vertices[7], vertices[10]),
             new Triangle(vertices[0], vertices[10], vertices[11]),
 
             // 5 adjacent faces
             new Triangle(vertices[1], vertices[5], vertices[9]),
             new Triangle(vertices[5], vertices[11], vertices[4]),
             new Triangle(vertices[11], vertices[10], vertices[2]),
             new Triangle(vertices[10], vertices[7], vertices[6]),
             new Triangle(vertices[7], vertices[1], vertices[8]),
 
             // 5 faces around point 3
             new Triangle(vertices[3], vertices[9], vertices[4]),
             new Triangle(vertices[3], vertices[4], vertices[2]),
             new Triangle(vertices[3], vertices[2], vertices[6]),
             new Triangle(vertices[3], vertices[6], vertices[8]),
             new Triangle(vertices[3], vertices[8], vertices[9]),
 
             // 5 adjacent faces
             new Triangle(vertices[4], vertices[9], vertices[5]),
             new Triangle(vertices[2], vertices[4], vertices[11]),
             new Triangle(vertices[6], vertices[2], vertices[10]),
             new Triangle(vertices[8], vertices[6], vertices[7]),
             new Triangle(vertices[9], vertices[8], vertices[1])
         };
     }
 
 
     public void GenerateMesh()
     {
         SetupTriangles();
         RecurseUniformally(settings.minDepth);
         BuildMesh();
     }
 
     private void BuildMesh()
     {
         int trianglesLength = triangles.Count;
         int arraysLength = trianglesLength * 3;
 
         Vector3[] meshVertices = new Vector3[arraysLength];
         int[] meshTriangles = new int[arraysLength];
         for (int i = 0; i < trianglesLength; i++)
         {
             int aBaseIndex = i * 3;
             Triangle t = triangles[i];
 
             meshVertices[aBaseIndex] = PointOnSphere(t.v1);
             meshVertices[aBaseIndex + 1] = PointOnSphere(t.v2);
             meshVertices[aBaseIndex + 2] = PointOnSphere(t.v3);
 
             meshTriangles[aBaseIndex] = aBaseIndex;
             meshTriangles[aBaseIndex + 1] = aBaseIndex + 1;
             meshTriangles[aBaseIndex + 2] = aBaseIndex + 2;
         }
 
         mesh.Clear();
         mesh.vertices = meshVertices;
         mesh.triangles = meshTriangles;
         mesh.RecalculateNormals();
     }
 
     private Vector3 PointOnSphere(Vector3 p)
     {
         return p * settings.radius;
     }
 
     private void RecurseUniformally(int depth)
     {
         for (int i = 0; i < depth; i++)
         {
             List<Triangle> toRemove = new List<Triangle>();
             int tLength = triangles.Count;
 
             for (int ti = 0; ti < tLength; ti++)
             {
                 var t = triangles[ti];
                 if (t.isVisible)
                     RecurseTriangle(t);
                 toRemove.Add(t);
             }
 
             foreach (var t in toRemove)
             {
                 triangles.Remove(t);
             }
         }
     }
 
     private void RecurseTriangle(Triangle triangle)
     {
         triangles.AddRange(triangle.Recurse());
     }
 
 
 
 
 
 
 
     private class Triangle
     {
         /*
          *               v2
          *                *
          *               * *
          *              *   *
          *    adj1     * d2  *    adj2
          *            a ----- b
          *           * | d4  | *
          *          *   |   |   *
          *         * d1  | |  d3 *
          *    v1  * * * * c * * * *  v3
          *
          *              adj3
          *
          */
 
         public Vector3 v1;
         public Vector3 v2;
         public Vector3 v3;
 
         // Adjacents triangles
         public Triangle adj1;
         public Triangle adj2;
         public Triangle adj3;
 
         // Descendants triangles, or null
         Triangle desc1;
         Triangle desc2;
         Triangle desc3;
         Triangle desc4;
 
         // Parent triangle, or null
         Triangle parent;
 
         public bool isVisible = true;
 
         // current recursive depth
         int depth;
 
 
         public Triangle(Vector3 v1, Vector3 v2, Vector3 v3)
         {
             this.v1 = v1;
             this.v2 = v2;
             this.v3 = v3;
         }
         public Triangle(Vector3 v1, Vector3 v2, Vector3 v3, int depth, Triangle parent)
         {
             this.v1 = v1;
             this.v2 = v2;
             this.v3 = v3;
             this.depth = depth;
             this.parent = parent;
         }
 
 
         public Triangle[] Recurse()
         {
             int newDepth = depth + 1;
 
             Vector3 a = Utility.GetVertexToUnitSphere(Utility.GetMidpoint(v1, v2));
             Vector3 b = Utility.GetVertexToUnitSphere(Utility.GetMidpoint(v2, v3));
             Vector3 c = Utility.GetVertexToUnitSphere(Utility.GetMidpoint(v1, v3));
 
             desc1 = new Triangle(v1, a, c, newDepth, this);
             desc2 = new Triangle(a, v2, b, newDepth, this);
             desc3 = new Triangle(c, b, v3, newDepth, this);
             desc4 = new Triangle(b, c, a, newDepth, this);
 
             // Adjacencies
 
             isVisible = false;
 
             return new Triangle[] { desc1, desc2, desc3, desc4 };
         }
     }
 
 
 
     private static class Utility
     {
         // Get a vector to the unit sphere.
         public static Vector3 GetVertexToUnitSphere(Vector3 v)
         {
             return v.normalized;
         }
 
         // Find the midpoint between two 3D points.
         public static Vector3 GetMidpoint(Vector3 p1, Vector3 p2)
         {
             return Vector3.Lerp(p1, p2, .5f);
         }
     }
 }


capture-decran-2022-01-17-a-195954.png (269.2 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 Bunny83 · Jan 17 at 04:34 PM

Well, you haven't shared any of your code so we have no idea how you generate your vertex normals because those are the important things to make it "look" smooth. Though for a sphere around the local center at (0,0,0) the normal is simply the vertext position normalized. Since we see the edges in your image, that's most likely not what you're doing. We also don't know if and how much of the vertices you have actually shared between the triangles. Keep in mind if you're planning of texturing the sphere you will need a UV seam somewhere, otherwise you would have one triangle strip having its texture coordinates flipped. So at least at the seam you would need duplicated vertices.

edit


Ok since you have posted your code we can see the problem. You create several completely unconnected triangles and you don't specify any normals yourself. While it is possible to have all triangles disconnected (so no shared vertices at all), however you can not use RecalculateNormals in that case. Each triangle is on its own. So when the normals for the vertices of that triangle are calculated, they would be perpendicular to that triangle face and you get that flat-shading you're seeing at the moment. If the vertices would be shared, RecalculateNormals would work "better". Though at UV seams the automatic calculation would still fail. You need to provide the normals yourself. As I already said the normal for each vertex position is equal to the position, just normalized. Since your positions are already normalized, they are literally the same. That means you don't even need a seperate "normals" array or List as usual but you can simply use the same array for the normals ^^. So instead of doing this:

     mesh.Clear();
     mesh.vertices = meshVertices;
     mesh.triangles = meshTriangles;
     mesh.RecalculateNormals();

you just do this:

     mesh.Clear();
     mesh.vertices = meshVertices;
     mesh.normals = meshVertices;
     mesh.triangles = meshTriangles;

Make sure you remove the "RecalculateNormals" call.

Of course, if you may desire to scale the sphere in the mesh / vertices itself, you should use a seperate array for the normals (which should be normalized) and the positions (which do not need to be normalized).

Comment
Add comment · Show 2 · 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 Bunny83 · Jan 17 at 06:44 PM 0
Share

Note when you have a mesh that has shared vertices, you can use my subdivision routine I wrote over here. I actually made a more advanced version on the unity wiki, which unfortunately is down (though still in the archive). This subdivision routine will try to keep as shared edges shared after the subdivision. Though currently it does only subdivide, it does not renormalize after each subdivision step which is required for an icosphere. UVs are also subdivided linearly. Though currently your "sphere" does not have any texture coordinates, so that might be another task on your list anyways ^^.

avatar image playsky · Jan 18 at 12:40 AM 0
Share

@Bunny83 Thank you very much as you said it works very well when I remove the "RecalculateNormals" call and set the normals to my vertices. I will rebuild my system to have shared vertices ( I will base myself on your subdivision routine which is very interested ! ), I think it would be better.

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

150 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

Related Questions

Procedural Mesh Generation: Creating a spherical sector 2 Answers

Sphere made of cubes algorithm 4 Answers

Procedural mesh artifacts. 1 Answer

Is it safe to assume that all platforms can support a mesh with 4 sets of UVs ? 0 Answers

Getting mesh length (x,z) 1 Answer


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