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 Maffew · Jul 02, 2014 at 03:24 PM · procedural

Delete vertices from a mesh at runtime

Hi all,

I've been attempting to create a C# script that removes vertices above a certain point in world space. So far I have managed to create a script that makes the offending part of the mesh transparent but I'm having alpha issues (particularly with the DOF effect.) I also thought it would be more efficient if the vertices didnt exist at all. I'm VERY new to programming so I apologise in advance for the upcoming code!

using UnityEngine; using System.Collections; using System.Collections.Generic;

public class DeleteVertsByHeight : MonoBehaviour {

 public GameObject heightReferenceObject;
 public float heightReferenceFloat = 0;
 float heightCutOff;
 public float errorAdjustment=0;

 void Start() {
     if (heightReferenceObject != null) {
                     heightCutOff = heightReferenceObject.transform.position.y;
             }
     else{
         heightCutOff = heightReferenceFloat;
     }
     Mesh mesh = GetComponent<MeshFilter>().mesh;
     int[] triangles = mesh.triangles;
     Vector3[] vertices = mesh.vertices;
     Vector2[] uv = mesh.uv;
     Vector3[] normals = mesh.normals;
     List<Vector3> vertList = new List<Vector3>();
     List<Vector2> uvList = new List<Vector2>();
     List<Vector3> normalsList = new List<Vector3>();
     List<int> trianglesList = new List<int>();

     int i = 0;
     while (i < vertices.Length) {
         Vector3 tempPos = transform.TransformPoint(vertices[i].x, vertices[i].y, vertices[i].z);
         if(tempPos.y < (heightCutOff+errorAdjustment))
         {
             vertList.Add (vertices[i]); 
             uvList.Add (uv[i]);
             normalsList.Add (normals[i]);
             trianglesList.Add (triangles[i]); //Don't think this is generating them in the correct order!
         }
         i++;
     }
     triangles = trianglesList.ToArray ();
     vertices = vertList.ToArray ();
     uv = uvList.ToArray ();
     normals = normalsList.ToArray ();
     mesh.triangles = triangles;
     mesh.vertices = vertices;
     mesh.uv = uv;
     mesh.normals = normals;
 }

}

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

3 Replies

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

Answer by robertbu · Jul 02, 2014 at 04:30 PM

This can be a tricky problem. I'm not sure what you want to do about the edges. That is, a triangle may start below your height, and then extend above it. Deleting the triangle may result in a ragged edge. If you don't care (or if it a non-issue because of the nature of your mesh), then as a first try, consider leaving the vertices alone and just eliminating any triangles that have any vertex above your 'heightCuttoff'. The Triangles array is composed of sets of three indices (into the vertices array). So you can just walk the array checking each set of three. If all the vertices are below your cutoff, add all three to a new array. If any are above, skip that set of three. This may get you want you want without deleting any vertices.

If you really want to eliminate the vertices, then you could do it in two steps:

  1. Build a new vertices list with vertices eliminated, but create a map from the old array position to the new array position. That is you would have an array of integers the size of the old vertices list. When a vertex is put into the new array, that position is stored in the integer array at the old vertex array position. If a vertex is eliminated, set the map value for that position to -1.

  2. Walk the triangle list building a new array of triangles. If any of the three vertices when indexed into the map array crated in step #1 are -1, don't move that triangle to the new list. Else, adjust the indices using the map and add the triangle to build the new list.

Comment
Add comment · Show 5 · 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 Maffew · Jul 02, 2014 at 04:47 PM 0
Share

Deleting the triangle may result in a ragged edge. If you don't care (or if it a non-issue because of the nature of your mesh),

This should be O$$anonymous$$ with the mesh I am using, or I could just use a combination of my existing solution and change the alpha per vert to cover the ragged edge.

The Triangles array is composed of sets of three indices (into the vertices array).

I'm not sure I follow this. I noticed that the triangle array is an int array. Does this mean that the first 3 entries in the vert array make up triangle #1, the next 3 make up triangle #2 etc etc?

Edit: Just realised that triangles will share verts so this won't be the case :P

avatar image robertbu · Jul 02, 2014 at 05:26 PM 0
Share

The triangle array are indices into the vertices array. The first three entries in the array form the first triangle, and the second three entries, the second triangle. For example the first six entries in the array might be:

 0,1,2,0,1,4   

These would be indexes into the vertices array. The first triangle would use the first three Vector3 positions in the vertices array. The second triangle would share the first two positions, but have a different third position.

avatar image robertbu · Jul 02, 2014 at 05:41 PM 0
Share

Here is a bit of untested sample code showing the logic:

     for (int i = 0; i < triangles.Length; i += 3) {
         if ((transform.TransformPoint(vertices[triangles[i  ]]).y < heightCutOff+errorAdjustment)  &&
             (transform.TransformPoint(vertices[triangles[i+1]]).y < heightCutOff+errorAdjustment)  &&
             (transform.TransformPoint(vertices[triangles[i+2]]).y < heightCutOff+errorAdjustment)) {
         
             newTriangles.Add (triangles[i]);
           newTriangles.Add (triangles[i+1]);
             newTriangles.Add (triangles[i+2]);
         }
     }
avatar image Graham-Dunnett ♦♦ · Jul 02, 2014 at 08:46 PM 0
Share

@$$anonymous$$affew - yes

avatar image robertbu · Jul 03, 2014 at 02:17 AM 0
Share

Does this mean that the first 3 entries in the vert array make up triangle #1, the next 3 make up triangle #2 etc etc?

@$$anonymous$$affew - no. The first three entries in the triangle array make up the first triangle. The second three make up the second triangle. The integers in the triangle array indicate what entries in the vertices array to use for each point of the triangle. By using integers as indices into the vertices array, many triangles can share the same vertex.

Note given your statements above about using vertex color and setting the alpha to 0, one thing you could do is to eli$$anonymous$$ate all the triangles where all three vertices are above your heightCutOff, and then use an alpha of 0 for any remaining points on triangles are above heightCutOff.

avatar image
2

Answer by Maffew · Jul 03, 2014 at 09:23 AM

@robertu that sample code helped massively, thanks!

here is my working code for anyone interested.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class DeleteVertsByHeight : MonoBehaviour {
 
     public GameObject heightReferenceObject;
     public float heightReferenceFloat = 0;
     float heightCutOff;
     public float errorAdjustment=0;
 
     void Start() {
 
         Mesh mesh = GetComponent<MeshFilter>().mesh;
         int[] triangles = mesh.triangles;
         Vector3[] vertices = mesh.vertices;
         Vector2[] uv = mesh.uv;
         Vector3[] normals = mesh.normals;
         List<Vector3> vertList = new List<Vector3>();
         List<Vector2> uvList = new List<Vector2>();
         List<Vector3> normalsList = new List<Vector3>();
         List<int> trianglesList = new List<int>();
 
 
         if (heightReferenceObject != null) {
                         heightCutOff = heightReferenceObject.transform.position.y;
                 }
         else{
             heightCutOff = heightReferenceFloat;
         }
 
         int i = 0;
         while (i < vertices.Length) {
                 vertList.Add (vertices[i]); 
                 uvList.Add (uv[i]);
                 normalsList.Add (normals[i]);
             i++;
         }
         for (int triCount = 0; triCount < triangles.Length; triCount += 3) {
             if ((transform.TransformPoint(vertices[triangles[triCount  ]]).y < heightCutOff+errorAdjustment)  &&
                 (transform.TransformPoint(vertices[triangles[triCount+1]]).y < heightCutOff+errorAdjustment)  &&
                 (transform.TransformPoint(vertices[triangles[triCount+2]]).y < heightCutOff+errorAdjustment)) {
                 
                 trianglesList.Add (triangles[triCount]);
                 trianglesList.Add (triangles[triCount+1]);
                 trianglesList.Add (triangles[triCount+2]);
             }
         }
 
 
         triangles = trianglesList.ToArray ();
         vertices = vertList.ToArray ();
         uv = uvList.ToArray ();
         normals = normalsList.ToArray ();
         //mesh.Clear();
         mesh.triangles = triangles;
         mesh.vertices = vertices;
         mesh.uv = uv;
         mesh.normals = normals;
     }
 }
 
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 tkoknordic · Apr 08, 2015 at 08:30 AM 0
Share

List function ToArray takes huge GC alloc if list is long. Is there better way in the terms of GC allocation size?

avatar image
0

Answer by radacadabra · May 08, 2020 at 12:46 AM

This is an old thread, but if you stumble upont his like I did, here is a better optimised code that does the same.

@Maffew code works (thanks btw!) but checks vertices for each triangle, so one vertex is checked multiple times for each triangle it makes. On smaller meshes it doesn't matter but for larger ones it adds up. Code below first checks all vertices once and marks them inside or not.

Also, there is no need (as far as I know) to rewrite vertices, uv, and normals - you can only adjust the triangles. This way, vertices, uv and normals that are not used by a triangle are just not used. Result is the same but but cutting is faster.

Code below cuts not only above certain y value, but above max and min y, x and z - basically you can cut a box from your mesh. It can of course be easily adjusted according to need.

             //set cut-off values
             float maxX;
             float minX;
             float maxY;
             float minY;
             float maxZ;
             float minZ;
 
             //set the buffer(padding)
             float buffer;
 
             maxX = maxX + buffer;
             minX = minX - buffer;
             maxY = maxY + buffer;
             minY = minY - buffer;
             maxZ = maxZ + buffer;
             minZ = minZ - buffer;
 
             Mesh mesh = meshClone.GetComponent<MeshFilter>().mesh;
             Vector3[] vertices = mesh.vertices;
             int[] triangles = mesh.triangles;
             List<int> newTriangles = new List<int>();
 
             float vertexX;
             float vertexY;
             float vertexZ;
 
             for (int i = 0; i < vertices.Length; i++)
             {
                 vertexX = transform.TransformPoint(vertices[i]).x;
                 vertexY = transform.TransformPoint(vertices[i]).y;
                 vertexZ = transform.TransformPoint(vertices[i]).z;
 
                 if (vertexX < maxX && vertexX > minX && vertexY < maxY && vertexY > minY && vertexZ < maxZ && vertexZ > minZ)
                 {
                     insideOrNot.Add(true);
                 }
                 else
                 {
                     insideOrNot.Add(false);
                 }
 
             }
 
             for (int i = 0; i < triangles.Length; i += 3)
             {
                 if (insideOrNot[triangles[i]] && insideOrNot[triangles[i + 1]] && insideOrNot[triangles[i + 2]])
                 {
                     newTriangles.Add(triangles[i]);
                     newTriangles.Add(triangles[i + 1]);
                     newTriangles.Add(triangles[i + 2]);
                 }
             }
 
             mesh.triangles = newTriangles.ToArray();

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 ml785 · May 21, 2020 at 11:31 AM 0
Share

Thanks for posting this! I'm intrigued but confused. What is 'insideOrNot'?

avatar image twobob ml785 · Jan 13 at 07:39 PM 0
Share
 private List<bool> insideOrNot = new List<bool>();

 public Transform meshClone;

 //set cut-off values
 public float maxX;
 public float $$anonymous$$X;
 public float maxY;
 public float $$anonymous$$Y;
 public float maxZ;
 public float $$anonymous$$Z;

 //set the buffer(padding)
 private float buffer;

should hold you

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Determine whether or not model is "inside out" 2 Answers

snapping objects at runtime 2 Answers

Combining meshes (different materials) together for rotation/translation 1 Answer

How can I use Substance materials in Unity? 2 Answers

Custom Mesh UV Problem 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