Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
1
Question by cccjjmm · Dec 31, 2017 at 09:43 PM · c#meshverticesplanetedit

how to make a planet

how to edit a spherical mesh already created in Autodesk Maya and edit its surface procedural to create a realistic planet it's possible?

example alt text alt text . . . . . . . sorry for my bad english

maxresdefault-1.jpg (255.5 kB)
maxresdefault.jpg (90.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
2
Best Answer

Answer by aldonaletto · Jan 01, 2018 at 02:42 PM

You could use Mathf.PerlinNoise(x,y) in order to generate "random" heights at each vertex. This function returns randomized and smoothed values between 0 and 1 according to the x,y coordinates passed to it, much like it was reading the values from a texture. We can get each vertex, combine somehow x,y with z in order to get a 2D pair and pass it to PerlinNoise to get the vertex height modifier. Since this value is between 0 and 1, we can also assign it as (height, 0) to the vertex uv coordinate, what allows us to have different colors according to the height via albedo texture.
There's a problem, however: it's necessary to recalculate normals after changing the vertices, but the Unity's builtin function Mesh.RecalculateNormals doesn't work fine in this case (it can't recognize neighbor vertices unless they're shared by neighbor triangles). The quick solution is to adopt Chris Marango's RecalculateNormals interesting function: it finds all neighbor vertices without relying on they being shared or not. It's a good idea to visit his blog, but as a convenience I've posted the script here too - just save it as a new C# script in your project.
The script that adds Perlin bumps to a mesh follows below, and must be attached to any mesh you want to modify. It includes a simple rotation function in Update in order to better demonstrate its results - just remove the rotation code if you don't need it.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class PerlinHills : MonoBehaviour {
 
     public float height=0.2f; // max height (model space)
     public float mult=200f; // perlin granularity
 
     public float vel=60f; // planet rotation speed degrees/second
 
     Vector3 offset;
 
     void Start () {
         // select a random offset
         offset = mult * Random.insideUnitSphere;
         CreateHills ();
     }
     
     float PerlinHeight(Vector3 v){
         Vector3 pos = v * mult + offset; // apply offset and mult
         pos.y += pos.z; pos.x -= pos.z; // combine x,y with z
         return Mathf.PerlinNoise (pos.x, pos.y); // return perlin noise
     }
 
     void CreateHills(){
         Mesh mesh = GetComponent<MeshFilter> ().mesh;
         Vector3[] verts = mesh.vertices;
         Vector2[] uvs = mesh.uv;
         for (int i = 0; i < verts.Length; i++) {
             Vector3 v = verts [i];
             float h = PerlinHeight (v); // get perlin value (0..1)
             verts [i] = v * (1 + height * h); // move vertex away from center by h*height
             uvs [i] = new Vector2 (h, 0); // set uv to allow different colors according to height
         }
         mesh.vertices = verts; // set the modified vertices...
         mesh.uv = uvs; // and uvs
         // update normals without Unity limitations
         NormalSolver.RecalculateNormals (mesh, 60f);
     }
 
     void Update () {
         // demo: just rotate planet
         transform.Rotate (Vector3.up, Time.deltaTime * vel);
     }
 
 }

This is Chris Marango's NormalSolver class - just save it in your project as a new C# script (don't assign it to any object):

 /* 
  * The following code was taken from: http://schemingdeveloper.com
  *
  * Visit our game studio website: http://stopthegnomes.com
  *
  * License: You may use this code however you see fit, as long as you include this notice
  *    without any modifications.
  *
  *    You may not publish a paid asset on Unity store if its main function is based on
  *    the following code, but you may publish a paid asset that uses this code.
  *
  *    If you intend to use this in a Unity store asset or a commercial project, it would
  *    be appreciated, but not required, if you let me know with a link to the asset. If I
  *    don't get back to you just go ahead and use it anyway!
  */
 
 using System;
 using System.Collections.Generic;
 using UnityEngine;
 
 public static class NormalSolver
 {
     /// <summary>
     ///     Recalculate the normals of a mesh based on an angle threshold. This takes
     ///     into account distinct vertices that have the same position.
     /// </summary>
     /// <param name="mesh"></param>
     /// <param name="angle">
     ///     The smoothing angle. Note that triangles that already share
     ///     the same vertex will be smooth regardless of the angle! 
     /// </param>
     public static void RecalculateNormals(this Mesh mesh, float angle) {
         var cosineThreshold = Mathf.Cos(angle * Mathf.Deg2Rad);
 
         var vertices = mesh.vertices;
         var normals = new Vector3[vertices.Length];
 
         // Holds the normal of each triangle in each sub mesh.
         var triNormals = new Vector3[mesh.subMeshCount][];
 
         var dictionary = new Dictionary<VertexKey, List<VertexEntry>>(vertices.Length);
 
         for (var subMeshIndex = 0; subMeshIndex < mesh.subMeshCount; ++subMeshIndex) {
 
             var triangles = mesh.GetTriangles(subMeshIndex);
 
             triNormals[subMeshIndex] = new Vector3[triangles.Length / 3];
 
             for (var i = 0; i < triangles.Length; i += 3) {
                 int i1 = triangles[i];
                 int i2 = triangles[i + 1];
                 int i3 = triangles[i + 2];
 
                 // Calculate the normal of the triangle
                 Vector3 p1 = vertices[i2] - vertices[i1];
                 Vector3 p2 = vertices[i3] - vertices[i1];
                 Vector3 normal = Vector3.Cross(p1, p2).normalized;
                 int triIndex = i / 3;
                 triNormals[subMeshIndex][triIndex] = normal;
 
                 List<VertexEntry> entry;
                 VertexKey key;
 
                 if (!dictionary.TryGetValue(key = new VertexKey(vertices[i1]), out entry)) {
                     entry = new List<VertexEntry>(4);
                     dictionary.Add(key, entry);
                 }
                 entry.Add(new VertexEntry(subMeshIndex, triIndex, i1));
 
                 if (!dictionary.TryGetValue(key = new VertexKey(vertices[i2]), out entry)) {
                     entry = new List<VertexEntry>();
                     dictionary.Add(key, entry);
                 }
                 entry.Add(new VertexEntry(subMeshIndex, triIndex, i2));
 
                 if (!dictionary.TryGetValue(key = new VertexKey(vertices[i3]), out entry)) {
                     entry = new List<VertexEntry>();
                     dictionary.Add(key, entry);
                 }
                 entry.Add(new VertexEntry(subMeshIndex, triIndex, i3));
             }
         }
 
         // Each entry in the dictionary represents a unique vertex position.
 
         foreach (var vertList in dictionary.Values) {
             for (var i = 0; i < vertList.Count; ++i) {
 
                 var sum = new Vector3();
                 var lhsEntry = vertList[i];
 
                 for (var j = 0; j < vertList.Count; ++j) {
                     var rhsEntry = vertList[j];
 
                     if (lhsEntry.VertexIndex == rhsEntry.VertexIndex) {
                         sum += triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex];
                     } else {
                         // The dot product is the cosine of the angle between the two triangles.
                         // A larger cosine means a smaller angle.
                         var dot = Vector3.Dot(
                             triNormals[lhsEntry.MeshIndex][lhsEntry.TriangleIndex],
                             triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex]);
                         if (dot >= cosineThreshold) {
                             sum += triNormals[rhsEntry.MeshIndex][rhsEntry.TriangleIndex];
                         }
                     }
                 }
 
                 normals[lhsEntry.VertexIndex] = sum.normalized;
             }
         }
 
         mesh.normals = normals;
     }
 
     private struct VertexKey
     {
         private readonly long _x;
         private readonly long _y;
         private readonly long _z;
 
         // Change this if you require a different precision.
         private const int Tolerance = 100000;
 
         // Magic FNV values. Do not change these.
         private const long FNV32Init = 0x811c9dc5;
         private const long FNV32Prime = 0x01000193;
 
         public VertexKey(Vector3 position) {
             _x = (long)(Mathf.Round(position.x * Tolerance));
             _y = (long)(Mathf.Round(position.y * Tolerance));
             _z = (long)(Mathf.Round(position.z * Tolerance));
         }
 
         public override bool Equals(object obj) {
             var key = (VertexKey)obj;
             return _x == key._x && _y == key._y && _z == key._z;
         }
 
         public override int GetHashCode() {
             long rv = FNV32Init;
             rv ^= _x;
             rv *= FNV32Prime;
             rv ^= _y;
             rv *= FNV32Prime;
             rv ^= _z;
             rv *= FNV32Prime;
 
             return rv.GetHashCode();
         }
     }
 
     private struct VertexEntry {
         public int MeshIndex;
         public int TriangleIndex;
         public int VertexIndex;
 
         public VertexEntry(int meshIndex, int triIndex, int vertIndex) {
             MeshIndex = meshIndex;
             TriangleIndex = triIndex;
             VertexIndex = vertIndex;
         }
     }
 }

I'm also including a simple (and ugly) height-to-color texture that serves as an example on how to paint your planet according to the height (import and assign it to the Albedo texture in a new material, then assign the material to your planet):

alt text

OBS: The whole thing is intended as a hint on how to generate planets procedurally. You can replace the simple Perlin noise function by a 2D monochromatic texture where each point is a terrain height, for instance, in order to obtain more realistic elevations (the ones created by Unity's Perlin function let a lot to desire...)


heightcolors.png (27.2 kB)
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 cccjjmm · Jan 03, 2018 at 08:02 PM 0
Share

..........ty

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

425 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image 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

Best way to optimize mesh updating through code? 1 Answer

Setting mesh.vertices to a 3-dimensional array 1 Answer

Mesh adaption 1 Answer

How to edit a mesh from a script 1 Answer

Get all vertices in gameObject to array. 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