移除具有布料组件的网格中的三角形

huangapple go评论75阅读模式
英文:

Removing Triangles of mesh having Cloth component

问题

I have implemented the remove triangle for removing selected triangles using raycast in unity. My implementation works fine with mesh in having no components of cloth but when I am adding the cloth component, i am still able to remove the triangles but there is an issue. It removes the triangles and when I stop the game and re-run it, it shows me the result properly and the removal of triangles are still visible unless I restart the unity.

我已经实现了使用射线投射在Unity中移除选定三角形的功能。我的实现在没有布料组件的网格上运行良好,但当我添加布料组件时,仍然可以移除三角形,但存在问题。它移除了三角形,但当我停止游戏并重新运行时,它会正确显示结果,三角形的移除仍然可见,除非重新启动Unity。

I have shared several screenshots, from the beginning till the end step by step along with the code.

我已经分享了一些截图,从开始到最后一步一步地以及包括代码。

My goal here is to see result during run-time. I am confused what should I do or what is wrong in my code. I will appreciate any guidance. Thank you in Advance.

我的目标是在运行时看到结果。我不确定应该做什么或我的代码有什么问题。我将感激任何指导。提前谢谢。

英文:

I have implemented the remove triangle for removing selected triangles using raycast in unity. My implementation works fine with mesh in having no components of cloth but when I am adding the cloth component, i am still able to remove the triangles but there is an issue. It removes the triangles and when I stop the game and re-run it, it shows me the result properly and the removal of triangles are still visible unless I restart the unity.

I have shared several screenshots, from the beginning till the end step by step along with the code.

> 1:Before running the scene
>
> 2:Removing the triangles of the mesh having cloth component using
> raycast

>
> 3:Stoped the scene
>
> 4:Re-run the scene and we can see the result of separation of plane
> after triangles removed vertically

My goal here is to see result during run-time. I am confused what should I do or what is wrong in my code. I will appreciate any guidance. Thank you in Advance.

using System;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using System.Numerics;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Vector4 = UnityEngine.Vector4;
public  class RemoveTriangle : MonoBehaviour
{
// [Header("Game Object")][Tooltip("The game object that will be removed its triangles")]
//public GameObject spherePrefab;
// Better to reference those already in the Inspector
[Header("Mesh Files to Load")]
/* [SerializeField][Tooltip("Drag and drop the mesh files you want to load")] private Obi.ObiBlueprintFilterMask meshFilter;
[SerializeField][Tooltip("Drag and drop the mesh files you want to load")] private Obi.ObiParticleRenderer meshRenderer;
[SerializeField][Tooltip("Drag and drop the mesh files you want to load")] private SkinnedMeshRenderer meshCollider;*/
//[SerializeField] [Range(1.0f, 3.0f)] public float raycastSize = 1.0f;
[Header("Origin and Target objects")]
[Tooltip("Drag and drop the origin and target objects")]public Transform SelectOrigin;
[Tooltip("Drag and drop the origin and target objects")] public  SkinnedMeshRenderer skinnedMeshRenderer;
[Header("Raycast Distance")][Tooltip("The distance of the raycast")]
[SerializeField][Range(0.1f,20.0f)]public float MaxDistance = 10f;
public Mesh mesh;
public bool useTethres;
private void Start()
{
mesh = skinnedMeshRenderer.sharedMesh;
}
private void Update()
{
DeleteTriangle();
}
void DeleteTriangle()
{//raycast from mouse position
Mesh newMesh = new Mesh();
if (Input.GetKey(KeyCode.C))
{//raycast from mouse position
Ray ray = new Ray(SelectOrigin.position, SelectOrigin.forward);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, MaxDistance))
{//if raycast hits a triangle
Debug.DrawRay(SelectOrigin.position,
skinnedMeshRenderer.transform.forward - SelectOrigin.position, 
Color.red);
Debug.Log("Triangle Removed at: " + hit.point + "/" + hit.triangleIndex + "/" + hit.normal);
int index = hit.triangleIndex * 3;
newMesh.vertices = mesh.vertices;
newMesh.uv = mesh.uv;
newMesh.tangents = mesh.tangents;
newMesh.normals = mesh.normals;
int[] triangles =mesh.triangles;
int vertIndex_1 = triangles[hit.triangleIndex * 3 + 0];
int vertIndex_2 = triangles[hit.triangleIndex * 3 + 1];
int vertIndex_3 = triangles[hit.triangleIndex * 3 + 2];
// Get the vertices for this triangle
var vert_1 = newMesh.vertices[vertIndex_1];
var vert_2 = newMesh.vertices[vertIndex_2];
var vert_3 = newMesh.vertices[vertIndex_3];
// Get the uv for this triangle
var uv_1 = newMesh.uv[vertIndex_1];
var uv_2 = newMesh.uv[vertIndex_2];
var uv_3 = newMesh.uv[vertIndex_3];
//Get the Normals for this triangle
var normal_1 = mesh.normals[vertIndex_1];
var normal_2 = mesh.normals[vertIndex_2];
var normal_3 = mesh.normals[vertIndex_3];
//Get Tangents for this triangle
Vector4 tangent_1 = mesh.tangents[vertIndex_1];
Vector4 tangent_2 = mesh.tangents[vertIndex_2];
Vector4 tangent_3 = mesh.tangents[vertIndex_3];
// Get the positions for the vertices
var vertPos_1 = newMesh.vertices[vertIndex_1];
var vertPos_2 = newMesh.vertices[vertIndex_2];
var vertPos_3 = newMesh.vertices[vertIndex_3];
// Now for all three vertices we first check if any other triangle if using it
// by simply count how often the indices are used in the triangles list
var verticesOccur_1 = 0;
var verticesOccur_2 = 0;
var verticesOccur_3 = 0;
//for all three vertices of cloth mesh check if any other triangle is using it by simply count how often the indices are used in the triangles list
for (var i = 0; i < triangles.Length; i++)
{
if (triangles[i] == vertIndex_1)
verticesOccur_1++;
if (triangles[i] == vertIndex_2)
verticesOccur_2++;
if (triangles[i] == vertIndex_3)
verticesOccur_3++;
}//end for
// Remove the vertices
if (verticesOccur_1 == 1)
newMesh.vertices[vertIndex_1] = Vector3.zero;
if (verticesOccur_2 == 1)
newMesh.vertices[vertIndex_2] = Vector3.zero;
if (verticesOccur_3 == 1)
newMesh.vertices[vertIndex_3] = Vector3.zero;
// Remove the uv
if (verticesOccur_1 == 1)
newMesh.uv[vertIndex_1] = Vector2.zero;
if (verticesOccur_2 == 1)
newMesh.uv[vertIndex_2] = Vector2.zero;
if (verticesOccur_3 == 1)
newMesh.uv[vertIndex_3] = Vector2.zero;
// Remove the normals
if (verticesOccur_1 == 1)
mesh.normals[vertIndex_1] = Vector3.zero;
if (verticesOccur_2 == 1)
mesh.normals[vertIndex_2] = Vector3.zero;
if (verticesOccur_3 == 1)
mesh.normals[vertIndex_3] = Vector3.zero;
// Remove the tangents
if (verticesOccur_1 == 1)
mesh.tangents[vertIndex_1] = Vector4.zero;
if (verticesOccur_2 == 1)
mesh.tangents[vertIndex_2] = Vector4.zero;
if (verticesOccur_3 == 1)
mesh.tangents[vertIndex_3] = Vector4.zero;
// Find the intersecting triangles by checking if the ray intersects with their vertices
//var intersectingTriangles = new List<int>();
for (int i = 0; i < triangles.Length; i += 3)
{
if (triangles[i] == triangles[index] && triangles[i + 1] == triangles[index + 1] && triangles[i + 2] == triangles[index + 2])
{
triangles[i] = triangles[triangles.Length - 3];
triangles[i + 1] = triangles[triangles.Length - 2];
triangles[i + 2] = triangles[triangles.Length - 1];
}
}
newMesh.triangles= triangles;
skinnedMeshRenderer.sharedMesh = newMesh;
//update the mesh with the new vertices, uv, normals and tangents
mesh.vertices = newMesh.vertices;
mesh.uv = newMesh.uv;
mesh.tangents = newMesh.tangents;
mesh.normals =newMesh.normals;
//update the tirangles
//newMesh.triangles = triangles;
//update the mesh with the new triangles
mesh.triangles = newMesh.triangles;
//update the mesh with the new vertices, uv, normals and tangents
}//end of if
else
{
Debug.Log("No Triangle to remove" + hit.point);
}//end of if hit.triangleIndex
}//end of remove triangle
}//end of class
}//end of class

答案1

得分: 0

因为你正在编辑共享的网格,也许这不是你期望的:

mesh = skinnedMeshRenderer.sharedMesh;
......
mesh.vertices = newMesh.vertices;

Plane 网格是内置网格,所以当 Unity 重新启动时会还原。因为你的代码,这个错误不会每次都发生,但如果没有布料组件,有时可能会发生。

你可以在启动时克隆网格:

private void Start()
{
    mesh = Instantiate(skinnedMeshRenderer.sharedMesh);
    skinnedMeshRenderer.sharedMesh = mesh;
}

然后你就不再需要 newMesh,现在可以直接编辑 mesh

英文:

Because you are editing the shared mesh, maybe this is not what you expected:

mesh = skinnedMeshRenderer.sharedMesh;
......
mesh.vertices = newMesh.vertices;

The Plane mesh is a built-in mesh, so it is reverted when Unity is relaunched. Because of your code, this error does not occur every time, but without the cloth component, it can occur sometimes.

You can clone the mesh on start:

private void Start()
{
mesh = Instantiate(skinnedMeshRenderer.sharedMesh);
skinnedMeshRenderer.sharedMesh = mesh;
}

Then you don't need newMesh anymore, you can directly edit mesh now.

huangapple
  • 本文由 发表于 2023年3月9日 20:04:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75684367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定