개발 · 컴퓨터공학/three.js / / 2024. 7. 2. 09:12

Threejs Cloth Tailor 개발일지 - Vertex Index Reordering 정점 인덱스 재정리, edge 기준 face들의 group잡기

728x90
반응형

 

발상의 전환 

생각을 좀 정리해보고, 조언을 구해보았다 

 

edge를 기준으로 자르게 될 때, 이전까지는 방법을 못찾아서 camera의 view vector을 이용해서

edge를 포함한 plane을 만들고 이를 기준으로 face들을 edge의 양쪽으로 구분하려고 했으나

 

유체와는 반대로 의류와 같이 규칙적이고 규격있는 mesh를 다룰 때는 index를 이용하는 과정이 반드시 필요하다는 조언을 얻었다.

실제로 vertex index의 규칙을 이용할 수 있다면 vertex 기준으로 탐색같이 복잡한 연산을 할 필요가 없어서 방법을 찾을 수 있을 것 같다.

 

그래서 이제는 mesh의 vertex index를 재정리해서 edge를 기준으로 분리할 수 있는 방법을 찾아보려고 한다 

vertex index reordering 정점 인덱스 재정리

현재 인덱스가 그림처럼 규칙성 있게 정렬되는 방법을 찾으려고 한다 

정렬되어있는 index 구조에서는 edge기준으로 자른다고 했을 때 방법을 찾을 수 있을지도 모른다

 

vertex neighbor에 대한 생각

인덱스 재정리를 생각하다 잠시, vertex neighbor에 대해서 고민을 하게 되었다 

index정리를 하더라도 자르는 방향에 따라 애매한 점이 있는데,

 

이럴 바에는 neighbor 정보를 가져올 수 있는 수단이 있는게 더 편하지 않을까 싶다

mesh의 geometry에서 vertex index를 주면 그 이웃 vertex index를 가져오는 방법이 있을까? 

많은 연산을 하지 않고? 

 

찾아보니 직접적으로 제공하지는 않는다

현재 vertex가 구조체 형식으로 되어 링크되어있지 않기 때문에 이걸 직접 만들어야 하나 싶다 

 

edge 기준 face들의 group 구분하기 

조금 생각해봤는데 위 방법으로 하면 edge 기준으로 양방향으로 face를 구분할 수 있을 것 같다

그럼 굳이 인덱스 정렬을 하지 않아도 되는 방법이라서

바로 테스트 해보자

 

먼저 edge vertex list가 input 되어야한다 

 

import * as THREE from "three";

export function edgeCut(mesh: THREE.Mesh, vertexIdxList: number[]){
  let edgeFaces:[number,number,number][] = []
  const faces = mesh.geometry.index?.array!

  // edge를 포함한 face들 모두 찾기
  // find all face include edge
  for (let i = 0; i < faces?.length; i+=3) {
    const curFace: [number, number, number] = [faces[i], faces[i + 1], faces[i + 2]];

    // Check if curFace includes any vertex from vertexIdxList
    if (vertexIdxList.some(vertex => curFace.includes(vertex))) {
      edgeFaces.push(curFace)
    }
  }

  // edgeFaces에 포함된 모든 정점의 인덱스를 추출
  const edgeVertices = new Set<number>()
  edgeFaces.forEach(face => {
    face.forEach(vertex => edgeVertices.add(vertex))
  })
  const edgeVertexList = Array.from(edgeVertices)

  const edgeFirstVertex = edgeVertexList[0]
  let AGroupFaces: [number, number, number][] = []
  let BGroupFaces: [number, number, number][] = [...edgeFaces]
  let processedVertices = new Set<number>()

  function addConnectedFaces(vertex: number) {
    for (let i = 0; i < BGroupFaces.length; i++) {
      const face = BGroupFaces[i]
      if (face.includes(vertex)) {
        AGroupFaces.push(face)
        BGroupFaces.splice(i, 1)
        i--

        // Add unprocessed vertices from this face to the queue
        face.forEach(v => {
          if (!processedVertices.has(v) && !vertexIdxList.includes(v)) {
            processedVertices.add(v)
            addConnectedFaces(v)
          }
        })
      }
    }
  }

  processedVertices.add(edgeFirstVertex)
  addConnectedFaces(edgeFirstVertex)

  console.log("AGroupFaces:", AGroupFaces)
  console.log("BGroupFaces:", BGroupFaces)
}

그림대로 로직을 짜서 테스트 해보고 있는 중이다

edge를 포함한 face들을 모두 찾는 것부터 문제가 생겨 디버깅을 해보고 있었다

 

그림의 경우 나와야하는 face는 vertex 2,0 번을 하나라도 포함한 모든 face가 나와야한다

 

딱 10개로 정확히 edge를 포함한 모든 face들이다 

 

그 다음으로 edge faces의 모든 정점 인덱스 추출이 잘 진행되는지

 

vertex 1679와 4를 제외한 10개의 vertex가 잘 들어가 있다

 

아 근데 edge first vertex가 edge외의 vertex를 가져야하고

생각해보니까 1677이나 5도 담으면 안된다.

 

생각해보니 처음에 vertex 하나를 고를 때 아무 vertex나 넣지 않고

edge vertex를 두 개 이상 가진 face를 고르는 조건으로 하면 무조건 edge의 위쪽 혹은 아래쪽이 잡히게 될 것이다 

 

조건을 수정해보자 

 

  // select firstCheckVertex 
  let firstCheckVertex: number | null = null;
  for (const face of edgeFaces) {
    const idxInList = face.filter(v => vertexIdxList.includes(v)).length;
    if (idxInList === 2) {
      firstCheckVertex = face.find(v => !vertexIdxList.includes(v))!;
      if (firstCheckVertex !== undefined && edgeVertexList.includes(firstCheckVertex)) {
        break;
      }
    }
  }

first check vertex를 정의하는 조건을 두었다

  • vertexIdxList에 포함된 두 개의 정점 인덱스를 포함하는 면을 찾아 해당 면의 나머지 정점을 선택한다
  • 나머지 정점은 vertexIdxList에 포함되지 않는다

그리고 다시 디버깅 해보자 

 

이제 first check vertex가 1로

조건에 맞게 찾았다

 

근데 group을 분리해보니 이상하다

 


보면 edge가 하나고, 나머지 옆쪽 부분들이 이어져 있다고 생각해서 다 group되었다

B group에는 (2,0,1676) 하나의 face만 있다

 

이런 경우, edge가 끝까지 자르지 않은 경우 어떡할까 

edge의 vertex를 2개 포함한 face만 나누는...어?

 

새로운 조건을 생각했다

  • edge의 vertex를 2개 포함한 face에서 edge에 해당하지 않는 vertex index
    그러한 인덱스를 포함하는 face들만을 group에 담는 것이다 
  • edge의 vertex를 2개 포함한 face에서 edge에 해당하지 않는 vertex index를 'group vertex index'라고 하자
    group vertex index가 포함된 face를 구성하는 edge에 해당하지 않는 다른 vertex까지도 group vertex index에 추가한다 

위 두 조건이면 edge 위 아래로 구분할 수 있을 것 같다 

 

다른 방법 아이디어

다른 방법으로는 위와 같이 

edge vertex 2개 포함한 face를 group에 넣고

group에 있는 face의 vertex를 2개 포함한 face를 group face에 넣는 방법이 있다

 

이건 case 2로 분리해서 필요하다면 구현하는 것으로 하자 


일단 하던대로 조건을 주어 다시 수정해보자

 

추가한 조건대로 group vertex와 group face를 구분지으면 edge기준으로 주변 모든 face를 구분할 수 있을 것 같다

 

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유