- Home /
How do I place the matching Vector3 array values of a Vector3 array in a new array ?
hello , I am attempting to place the values of an array that are the same; inside of a separate.
this is a code i adopted and tried to use to move an objects verts , however; this script assigned points called "handles" to each vert as a child of the object . As a result , moving the handles results in simply pulling the mesh apart by individual verts.
I tried to group all the verts with the same Vector3 positions into an array and setting all the vector3 values of that array to be equal to the position of the handle.
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class VertHandler : MonoBehaviour
{
Mesh mesh;
Vector3[] verts;
Vector3 vertPos;
GameObject[] handles;
void OnEnable()
{
mesh = GetComponent<MeshFilter>().mesh;
verts = mesh.vertices;
foreach (Vector3 vert in verts)
{
vertPos = transform.TransformPoint(vert);
GameObject handle = new GameObject("handle");
handle.transform.position = vertPos;
handle.transform.parent = transform;
handle.tag = "handle";
//handle.AddComponent<Gizmo_Sphere>();
}
}
void OnDisable()
{
GameObject[] handles = GameObject.FindGameObjectsWithTag("handle");
foreach (GameObject handle in handles)
{
DestroyImmediate(handle);
}
}
void Update()
{
handles = GameObject.FindGameObjectsWithTag("handle");
for (int i = 0; i < verts.Length; i++)
{
verts[i] = handles[i].transform.localPosition;
}
mesh.vertices = verts;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}
Well, all your examples are about exact duplicates but in your title you said "similar". There's a huge difference. When dealing with exact duplicates you can simply compare them. If you want similar values (like Vector3(2.5f,3,6) and Vector3(2.49999f,3,6.00001)) then you have to be more clear how you define similar in your case. In the comment below you had a different example using strings / objects / whatever. What is your actual usecase? Vector3 values or something else?
What's the point of storing the same (or almost the same) values in an array? In this case you could simply store the value once and a counter that tells you how many of those values you have. The easiest way for that would be a Dictionary
which just stores a count for each unique Vector3.
Could you be a bit more specific if you want "similar" values or exact the same values?
i need to sort through all the verts of a mesh, find all the vert positions that are the same , store all those positions in an array .
I will change the question to be more specific .
Be careful with scripts like that. ExecuteInEdit$$anonymous$$ode can cause a lot of problems and can corrupt your assets as well as the current scene. It's usually better to write an editor script for things like that.
Answer by Bunny83 · Nov 11, 2014 at 06:05 PM
Ok, for mesh manipulations you actually want to store the indices of similar vertices so you can update them all at once. just copying the vector3 value won't help much since you don't know where it belongs in the actual vertices array.
I would suggest to use a helper class like:
public class VertHandle
{
public Vector3 pos;
public List<int> indices = new List<int>();
public Transform handle;
}
With that class you can create a unique handle for each vertex-group like this:
List<VertHandle> GenerateHandles(Vector3[] aVertices, float aThreshold)
{
float sqrThreshold = aThreshold*aThreshold;
List<VertHandle> result = new List<VertHandle>();
for(int i = 0; i < aVertices.Length; i++)
{
VertHandle h = null;
for(int n = 0; n < result.Count; n++)
{
if ((result[n].pos - aVertices[i]).sqrMagnitude < sqrThreshold)
{
h = result[n];
break;
}
}
// if there's no handle with that position yet, create one.
if(h == null)
{
h = new VertHandle() { pos = aVertices[i]};
h.handle = new GameObject("handle").transform;
h.handle.parent = transform;
h.handle.localPosition = aVertices[i];
h.handle.tag = "handle";
result.Add(h);
}
// add the current vertex to the indices list of that handle
h.indices.Add(i);
}
return result;
}
This gives you a list of handles. To apply the changes from the handles to your actual vertices, just use
void ApplyChanges(List<VertHandle> aHandles, Vector3[] aVertices)
{
for(int i = 0; i < aHandles.Count; i++)
{
Vector3 pos = aHandles[i].handle.localPosition;
for(int n = 0; n < aHandles[i].indices.Count; n++)
{
aVertices[aHandles[i].indices[n]] = pos;
}
}
}
Keep in mind when destroying the handles to use
foreach (VertHandle h in handles)
{
DestroyImmediate(h.handle.gameObject);
}
Also make sure you store the handles List in your class in a member variable.
Sorry, I forgot to add the VertHandle instance to the result list. Added the it in line 24!
It works for me. If i "edit" the default cube i get 8 handles. However you should use ".shared$$anonymous$$esh" ins$$anonymous$$d of ".mesh" as .mesh will cause a memory leak as it duplicates the mesh. It's ment to be used at runtime only.
edit
You might want to create a copy of the mesh before starting editing it:
mesh = ($$anonymous$$esh)Instantiate(mf.shared$$anonymous$$esh); // create copy
mesh.name = mf.shared$$anonymous$$esh.name; // keep the old name (removes the "(clone)")
mf.shared$$anonymous$$esh = mesh; // use this mesh from now on
This might cause the mesh to "leak" as well since if the old mesh isn't used anymore by another object it's orphaned. When you save the scene Unity will notice you that the mesh has leaked. Unfortunately there's no clean way to detect that case.
Also I should mention that the mesh you're editing will be saved in the scene itself. Usually it's better to store it as asset in the project. But again that should be done from an editor script and not a runtime script with ExecuteInEdit$$anonymous$$ode.
hey,i'm having trouble putting this together correctly . I dont understand the definition of ApplyChanges. how did you put this code together ? sorry i'm not used to this method of coding using lists. oh , and and thank you for the answer.
Great, worked really well. I don't think i could have written it by myself . thanks again. I' going to edit it so that I can "select the verts" themselves and move them as I would in 3D modeling software , then I will share the code .
There is also the issue of mesh deformation when the script is place on an object . I'm going to work on making the verts "visible" and selectable first.
Your answer
Follow this Question
Related Questions
Setting position of a transform? 2 Answers
How to check if a vector 3 is in a vector 3 array c#. 1 Answer
How to call a function with Vector3[] argument? 3 Answers
C# Convert Vector3[] to Vector2[] 3 Answers