Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Any way of using a texture to deform a mesh in script?

Discussion in 'Scripting' started by FuzzyQuills, Oct 13, 2014.

  1. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Hi guys.

    I have a question; in order to make a dynamically generated planet, I need to be able to deform the mesh from a heightmap. To do this, I will need to be able to do it in script, so that the mesh collider can re-update itself. (This generation is a one-time thing, so no performance issue there.)

    But although I have an idea of how to do this, I am not sure of how to use a texture to do such deformation. Any ideas? I could just run perlin noise on the normals, but that could get messy... ;)
     
  2. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Step 1: for every vertex, use the uv co-ordinate to calculate pixel position
    Step 2: getpixel the texture to find height
    Step 3: scale vertex position by height

    Because it's a sphere, each verts position should also be it's normal, if a vert is at (0.5,0.6,0.7) and the height map color translates to a height of 2, the new vert position is just (1.0,1.2,1.4)

    To limit height to within a range, use lerp(minHeight, MaxHeight, Color)
     
  3. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Thank you for this information! :)

    I was presuming it was something along those lines... :D But how to calculate pixel position? Well, I just thought of a great way to do it: A mathf.lerp that takes the normalized UV coord and lerps the texture height with 0, like this (Assuming uv has already been gotten from the mesh! :D):
    Code (csharp):
    1.  
    2. var textureX = Mathf.Lerp(0,textureWidth, uv.x);
    3. var textureY = Mathf.Lerp(0,textureHeight, uv.y);
    4.  
    Any inefficiencies here? o_O
     
  4. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    You could replace those lines with...

    var textureX = textureWidth * uv.x;
    var textureY = textureHeight * uv.y;

    That would be the lowest optimization you could do to those lines :)
     
  5. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    The downside to this of course, is that the texture needs to be read/write enabled, and must use one of the correct formats
     
  6. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    @TwixEmma: Now why didn't I think of that? Anyway, I got it working. only problem now is that the texture, being that it isn't seamless, is generating mesh holes, so I will need to implement seamless perlin noise... :D

    But, come to think of it, just doing that multiply will save a couple of instructions, which is crucial to map loading time. :)

    @hpjohn: I actually needed the texture to be R/W anyway, so i could read the UV pixel from it, so no downside there. plus, I compute the texture at 256x256, which is a decent size for anything, being a heightmap... :)
     
  7. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I might as well post progress here:
    With no height... (Base mesh made in blender, I simply made a high-poly Ico_Sphere, then spheremapped the UVs onto it)
    PlanetGen_NoHeightMap.png
    With the PlanetGen script running:
    PlanetGen_WithHeightMap.png
    But what's that seam in the middle? that is why I need a hand in implementing seamless perlin noise... ;) Of course, if one of you guys (and/or girls) could help me, that would be great. :)
     
  8. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    there are two things I can think of, first maybe the base mesh has a seam in it, in which case the normals won't compute correctly. If not one possible solution could be myMesh.RecalculateNormals();
     
  9. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    99
    Game engines tend to consider vert counts differently to 3D packages - Non-unified normals, UV seams, and smoothing groups are all taken into account when Unity decides how many verts your mesh has - You probably have a UV seam along that line. If you want nice UVs AND nice repeating noise, you either need a tiling noise, or you need to use a shader that allows world space offsets (rather than UV space).
     
  10. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Instead of 'seamless perlin' just make 3d perlin
     
  11. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    @DigitalSalmon: That mesh you see there is actually deformed like that because of a seamed texture, it isn't anything to do with my UVs or vertices. (it is literally a 5x subdivided ico sphere from blender I am using.) Would sphere-mapping the mesh do the seam business? A seamless texture would help though! :)

    @TwixEmma: I am actually re-computing the normals after doing the mesh, so it isn't that, it's actually a mesh hole! i.e. torn down the middle.

    @hpjohn: 3D noise... I was actually looking around for some good frameworks and found a port of libnoise I could use. now to try it on my mesh...
     
  12. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    i like carmodys simplex noise
    http://stephencarmody.wikispaces.com/Simplex+Noise

    ps it is to do with the uv seam, because blender puts a uv seam in the sphere, when it imports into unity, it duplicates the verts along the same, so you cant recalc normals so simply
     
  13. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Oh, ok... in that case, how to make seamless spheremap? o_O
     
  14. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    You can't.
    Its impossible and has been a problem for hunderds of years (See cartography)
    The only way to truly seamlessly texture a sphere is with procedural techniques, like noise derived shading
     
  15. Deleted User

    Deleted User

    Guest

  16. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Thank you! I actually did this sort of map distort, except I ended up stretching the noise itself instead... :D Either way, most of the time, there is no longer a seam on my own mesh. will give this one a try though! :)

    BTW, your image I don't think is shared; I can't see it! o_O

    EDIT: Dem UVs... ARE AMAZING! :D
     
  17. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    99
    You could look into 'triplanar mapping'. Its a technique that projects from 3 worldspace axis and blends between the projections based on the surface normal - Very good for noisey/generic texturing where UVs are an issue. Would work well in your situation I reckon.
     
  18. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Well, I have heard of terrain-based tri-planar, but on a planet? o_O
    Will look this up. Also, the seaming issues are mostly gone now, as the noise algorithm is seamless, and produces some pretty nice results.