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

Threejs Cloth Tailor 개발일지 - edge 기준 group 분리 조건 구현, edge cutting 구현의 문제, 메쉬 자르기 구현 완료

728x90
반응형

 

 

edge 기준 group 분리 조건 정리

스스로도 생각하다보니 조건이 너무 복잡해서 헷갈린다

이번 아이디어를 실행하고 나면 다른 것들은 웬만하면 논문이나 상용되는 방법을 찾아서 사용해야한다 

 

스스로 생각해내는 것은 비효율적인 것 같다 

 

edge에 두 정점이 포함되어있는 face의 다른 하나 vertex를 담은 리스트를 twoVertexIsEdgeVertices 라고 하자

twoVertexIsEdgeVertices의 첫 번째 하나를 A group vertices index에 담고, 방금 담은 vertex index가 포함된 face에 다른 twoVertexIsEdgeVertices가 있으면 그것도 A group vertices index에 포함

포함된 vertex에 대해서 똑같이 진행해서 인접 face들에 포함된 twoVertexIsEdgeVertices들을 모두 A group vertices index에 담음

모두 담았으면 남은 twoVertexIsEdgeVertices 중 첫 번째 하나를 고르고 B group vertices index에 넣어서, A group vertices index에서 한 것과 같이 B group으로 진행
모두 group에 분리해서 넣고 나면 twoVertexIsEdgeVertices에는 값이 남지 않아야함

twoVertexIsEdgeVertices에 정상적으로 값이 남지 않게 다 분리했다면,
edgeVertices 정점 인덱스 중에서 다음 조건에 맞는 vertex index도 각 group마다 추가
  - A group vertex index의 vertex를 포함한 face중 edge에 해당하지 않는 다른 vertex를 찾아 A group vertex index에 포함한다
  - B group vertex index의 vertex를 포함한 face중 edge에 해당하지 않는 다른 vertex를 찾아 B group vertex index에 포함한다

여기까지 A / B group vertex index 완료

group vertex index를 A,B로 분리했으면 A group face에는 A group vertex index들이 포함되어있는 모든 face들을 담기
B group face에도 마찬가지로 B group vertex index들이 포함되어있는 모든 face들을 담기

 

상당히 복잡한 것 같다 빠르게 시도해보고 안되면 논문이나 일반적인 mesh cutting 방법을 사용하도록 하자 

 

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에 포함된 모든 정점의 인덱스를 추출
  // Extract the indices of all vertices contained in edgeFaces
  const edgeVertices = new Set<number>()
  edgeFaces.forEach(face => {
    face.forEach(vertex => edgeVertices.add(vertex))
  })
  const edgeVertexList = Array.from(edgeVertices)

  // find first add group vertex index 
  let twoVertexIsEdgeVertices: number[] | null = [];
  for (const face of edgeFaces) {
    const idxInList = face.filter(v => vertexIdxList.includes(v)).length;
    if (idxInList === 2) {
      twoVertexIsEdgeVertices.push(face.find(v => !vertexIdxList.includes(v))!)
    }
  }

  if (twoVertexIsEdgeVertices.length === 0) {
    console.log("No suitable vertex found for firstCheckVertex.");
    return;
  }

  let AGroupVertices = new Set<number>();
  let BGroupVertices = new Set<number>();

  // A group vertices 설정
  let stack = [twoVertexIsEdgeVertices[0]];
  while (stack.length > 0) {
    const vertex = stack.pop()!;
    if (!AGroupVertices.has(vertex)) {
      AGroupVertices.add(vertex);
      for (const face of edgeFaces) {
        if (face.includes(vertex)) {
          for (const v of face) {
            if (twoVertexIsEdgeVertices.includes(v) && !AGroupVertices.has(v)) {
              stack.push(v);
            }
          }
        }
      }
    }
  }

  // 남은 twoVertexIsEdgeVertices에서 B group vertices 설정
  twoVertexIsEdgeVertices = twoVertexIsEdgeVertices.filter(v => !AGroupVertices.has(v));
  if (twoVertexIsEdgeVertices.length > 0) {
    stack = [twoVertexIsEdgeVertices[0]];
    while (stack.length > 0) {
      const vertex = stack.pop()!;
      if (!BGroupVertices.has(vertex)) {
        BGroupVertices.add(vertex);
        for (const face of edgeFaces) {
          if (face.includes(vertex)) {
            for (const v of face) {
              if (twoVertexIsEdgeVertices.includes(v) && !BGroupVertices.has(v)) {
                stack.push(v);
              }
            }
          }
        }
      }
    }
  }

  // edgeVertices 정점 인덱스 중에서 각 group에 추가할 vertex 설정
  for (const vertex of edgeVertexList) {
    for (const face of edgeFaces) {
      if (face.includes(vertex)) {
        const otherVertices = face.filter(v => v !== vertex);
        if (AGroupVertices.has(vertex)) {
          for (const v of otherVertices) {
            if (!vertexIdxList.includes(v)) {
              AGroupVertices.add(v);
            }
          }
        } else if (BGroupVertices.has(vertex)) {
          for (const v of otherVertices) {
            if (!vertexIdxList.includes(v)) {
              BGroupVertices.add(v);
            }
          }
        }
      }
    }
  }

  // A group faces와 B group faces 설정
  let AGroupFaces: [number, number, number][] = [];
  let BGroupFaces: [number, number, number][] = [];
  for (const face of edgeFaces) {
    const verticesInA = face.filter(v => AGroupVertices.has(v)).length;
    const verticesInB = face.filter(v => BGroupVertices.has(v)).length;
    if (verticesInA === 3) {
      AGroupFaces.push(face);
    } else if (verticesInB === 3) {
      BGroupFaces.push(face);
    }
  }

  console.log("AGroupFaces:", AGroupFaces)
  console.log("BGroupFaces:", BGroupFaces)
  console.log("AGroupVertices:", Array.from(AGroupVertices));
  console.log("BGroupVertices:", Array.from(BGroupVertices));
}

코드구성을 해보았고 디버깅을 해보자

 

edge 기준 vertex index 및 face group분리 디버깅 

일단 edge에 정점을 두 개 가진 face에서 다른 하나 vertex들을 찾는 것은 잘되었다

1과 1676이면 성공이다 

 

처음 얻는 A group vertices도 1하나면 정상

B group vertices 도  1676으로 정상

 

아... A group vertices에 1,2,3만 들어가야하는데 이상한 값들이 들어갔다..

여기서 문제이다 

 

이제보니 group face를 가져오는 곳에서도 로직을 잘못 짰다

하나라도 포함되어있으면 가져오는 것이다 

 

코드 수정

  // edgeVertices 정점 인덱스 중에서 각 group에 추가할 vertex 설정
  for (const face of edgeFaces) {
    const otherVertices = face.filter(v => !vertexIdxList.includes(v));
    const AGroupFaceVertices = face.filter(v => AGroupVertices.has(v));
    const BGroupFaceVertices = face.filter(v => BGroupVertices.has(v));
    if (AGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!AGroupVertices.has(v)) {
          AGroupVertices.add(v);
        }
      }
    }
    if (BGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!BGroupVertices.has(v)) {
          BGroupVertices.add(v);
        }
      }
    }
  }

  // A group faces와 B group faces 설정
  let AGroupFaces: [number, number, number][] = [];
  let BGroupFaces: [number, number, number][] = [];
  for (const face of edgeFaces) {
    if (face.some(v => AGroupVertices.has(v))) {
      AGroupFaces.push(face);
    }
    if (face.some(v => BGroupVertices.has(v))) {
      BGroupFaces.push(face);
    }
  }

기존 group vertex index가 포함된 face의 다른 vertex 추가부분과

group face추가부분을 수정했다 

 

다시 디버깅 해보자 

아.. A group은 잘 되었는데

B group에 갑자기 5, 1677이 들어갔다. 이 두개는 어느 쪽 그룹에도 들어가면 안되는 vertex index인데..

 

디버깅하다가 원인을 찾았다 

B group에서 1676와 같은 face에 속한 1675까지는 포함되는데

그 이후에 1675와 같은 face에 속한 5를 포함하는 과정이 있는 것으로 보아

 

GroupVertices가 도중에 update되어서 생긴 문제이다 

이건 GroupVertices를 전후 두 개로 나누어서 해결하자 

 

  let newAGroupVertices = new Set(AGroupVertices);
  let newBGroupVertices = new Set(BGroupVertices);
  // edgeVertices 정점 인덱스 중에서 각 group에 추가할 vertex 설정
  for (const face of edgeFaces) {
    const otherVertices = face.filter(v => !vertexIdxList.includes(v));
    const AGroupFaceVertices = face.filter(v => AGroupVertices.has(v));
    const BGroupFaceVertices = face.filter(v => BGroupVertices.has(v));
    if (AGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!AGroupVertices.has(v)) {
          newAGroupVertices.add(v);
        }
      }
    }
    if (BGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!BGroupVertices.has(v)) {
          newBGroupVertices.add(v);
        }
      }
    }
  }
  // 추가된 vertex 반영
  newAGroupVertices.forEach(vertex => AGroupVertices.add(vertex));
  newBGroupVertices.forEach(vertex => BGroupVertices.add(vertex));

이렇게 수정해보고 테스트 해보자 

 

이제야 원하는대로 group vertices에 들어갔다 

 

이제 여기서 edge의 vertex들을 분리해서 B group face와 연결된 face에 대체해주자 

새로운 vertex 생성해서 B group에 대체하기 

import * as THREE from "three";

/**
 * @param mesh 
 * @param vertexIdxList: edge vertex index
 * @returns 
 */
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에 포함된 모든 정점의 인덱스를 추출
  // Extract the indices of all vertices contained in edgeFaces
  const edgeVertices = new Set<number>()
  edgeFaces.forEach(face => {
    face.forEach(vertex => edgeVertices.add(vertex))
  })
  const edgeVertexList = Array.from(edgeVertices)

  // find first add group vertex index 
  let twoVertexIsEdgeVertices: number[] | null = [];
  for (const face of edgeFaces) {
    const idxInList = face.filter(v => vertexIdxList.includes(v)).length;
    if (idxInList === 2) {
      twoVertexIsEdgeVertices.push(face.find(v => !vertexIdxList.includes(v))!)
    }
  }

  if (twoVertexIsEdgeVertices.length === 0) {
    console.log("No suitable vertex found for firstCheckVertex.");
    return;
  }

  let AGroupVertices = new Set<number>();
  let BGroupVertices = new Set<number>();

  // A group vertices 설정
  let stack = [twoVertexIsEdgeVertices[0]];
  while (stack.length > 0) {
    const vertex = stack.pop()!;
    if (!AGroupVertices.has(vertex)) {
      AGroupVertices.add(vertex);
      for (const face of edgeFaces) {
        if (face.includes(vertex)) {
          for (const v of face) {
            if (twoVertexIsEdgeVertices.includes(v) && !AGroupVertices.has(v)) {
              stack.push(v);
            }
          }
        }
      }
    }
  }

  // 남은 twoVertexIsEdgeVertices에서 B group vertices 설정
  twoVertexIsEdgeVertices = twoVertexIsEdgeVertices.filter(v => !AGroupVertices.has(v));
  if (twoVertexIsEdgeVertices.length > 0) {
    stack = [twoVertexIsEdgeVertices[0]];
    while (stack.length > 0) {
      const vertex = stack.pop()!;
      if (!BGroupVertices.has(vertex)) {
        BGroupVertices.add(vertex);
        for (const face of edgeFaces) {
          if (face.includes(vertex)) {
            for (const v of face) {
              if (twoVertexIsEdgeVertices.includes(v) && !BGroupVertices.has(v)) {
                stack.push(v);
              }
            }
          }
        }
      }
    }
  }

  let newAGroupVertices = new Set(AGroupVertices);
  let newBGroupVertices = new Set(BGroupVertices);
  // edgeVertices 정점 인덱스 중에서 각 group에 추가할 vertex 설정
  for (const face of edgeFaces) {
    const otherVertices = face.filter(v => !vertexIdxList.includes(v));
    const AGroupFaceVertices = face.filter(v => AGroupVertices.has(v));
    const BGroupFaceVertices = face.filter(v => BGroupVertices.has(v));
    if (AGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!AGroupVertices.has(v)) {
          newAGroupVertices.add(v);
        }
      }
    }
    if (BGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!BGroupVertices.has(v)) {
          newBGroupVertices.add(v);
        }
      }
    }
  }
  // 추가된 vertex 반영
  newAGroupVertices.forEach(vertex => AGroupVertices.add(vertex));
  newBGroupVertices.forEach(vertex => BGroupVertices.add(vertex));

  // A group faces와 B group faces 설정
  let AGroupFaces: [number, number, number][] = [];
  let BGroupFaces: [number, number, number][] = [];
  for (const face of edgeFaces) {
    if (face.some(v => AGroupVertices.has(v))) {
      AGroupFaces.push(face);
      continue;
    }
    if (face.some(v => BGroupVertices.has(v))) {
      BGroupFaces.push(face);
      continue;
    }
  }

  // vertexIdxList에 해당하는 vertex들 만큼 mesh index의 새로운 index로 추가하고 geometry attribute 업데이트
  const newVertices: number[] = [];
  const positionAttribute = mesh.geometry.attributes.position;
  const originalVertexCount = positionAttribute.count;

  for (const idx of vertexIdxList) {
    const x = positionAttribute.getX(idx);
    const y = positionAttribute.getY(idx);
    const z = positionAttribute.getZ(idx);
    newVertices.push(x, y, z);
  }

  const newVertexCount = newVertices.length / 3;
  const newIndicesMap = new Map<number, number>();
  for (let i = 0; i < newVertexCount; i++) {
    newIndicesMap.set(vertexIdxList[i], originalVertexCount + i);
  }

  const newPositionArray = new Float32Array(positionAttribute.array.length + newVertices.length);
  newPositionArray.set(positionAttribute.array);
  newPositionArray.set(newVertices, positionAttribute.array.length);
  mesh.geometry.setAttribute('position', new THREE.BufferAttribute(newPositionArray, 3));

  // index 배열 업데이트
  const newIndexArray = new Uint32Array(faces.length);
  newIndexArray.set(faces);
  for (const [oldIndex, newIndex] of newIndicesMap) {
    for (let i = 0; i < newIndexArray.length; i++) {
      if (newIndexArray[i] === oldIndex) {
        newIndexArray[i] = newIndex;
      }
    }
  }
  mesh.geometry.setIndex(new THREE.BufferAttribute(newIndexArray, 1));

  // B group face에서 기존에 vertexIdxList의 vertex에 해당되는 부분을 새로 추가한 index로 대체해서 반영
  for (let i = 0; i < BGroupFaces.length; i++) {
    const face = BGroupFaces[i];
    for (let j = 0; j < 3; j++) {
      if (vertexIdxList.includes(face[j])) {
        face[j] = newIndicesMap.get(face[j])!;
      }
    }
  }
}

새로 vertex를 생성하고 geometry 정보에 적용하기 까지 코드가 추가되었다

디버깅해보자 

 

일단 새로 생긴 vertex index(1681, 1682)들을 기존 edge인 2,0에 잘 매핑하고 있다 

 

하지만 index 배열 업데이트에서는 기존 index를 새로운 것으로 완전히 대체해버린다

그게 아니라 기존 index인 2,0을 유지하고 새로운 vertex index 1681, 1682를 추가하는건데.

 

이 index 배열 업데이트는 의미 없는 것 같고, B group face의 index를 대체한 후 geometry face를 업데이트하는 방향이 맞는 것 같다 

 

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에 포함된 모든 정점의 인덱스를 추출
  // Extract the indices of all vertices contained in edgeFaces
  const edgeVertices = new Set<number>()
  edgeFaces.forEach(face => {
    face.forEach(vertex => edgeVertices.add(vertex))
  })
  const edgeVertexList = Array.from(edgeVertices)

  // find first add group vertex index 
  let twoVertexIsEdgeVertices: number[] | null = [];
  for (const face of edgeFaces) {
    const idxInList = face.filter(v => vertexIdxList.includes(v)).length;
    if (idxInList === 2) {
      twoVertexIsEdgeVertices.push(face.find(v => !vertexIdxList.includes(v))!)
    }
  }

  if (twoVertexIsEdgeVertices.length === 0) {
    console.log("No suitable vertex found for firstCheckVertex.");
    return;
  }

  let AGroupVertices = new Set<number>();
  let BGroupVertices = new Set<number>();

  // A group vertices 설정
  let stack = [twoVertexIsEdgeVertices[0]];
  while (stack.length > 0) {
    const vertex = stack.pop()!;
    if (!AGroupVertices.has(vertex)) {
      AGroupVertices.add(vertex);
      for (const face of edgeFaces) {
        if (face.includes(vertex)) {
          for (const v of face) {
            if (twoVertexIsEdgeVertices.includes(v) && !AGroupVertices.has(v)) {
              stack.push(v);
            }
          }
        }
      }
    }
  }

  // 남은 twoVertexIsEdgeVertices에서 B group vertices 설정
  twoVertexIsEdgeVertices = twoVertexIsEdgeVertices.filter(v => !AGroupVertices.has(v));
  if (twoVertexIsEdgeVertices.length > 0) {
    stack = [twoVertexIsEdgeVertices[0]];
    while (stack.length > 0) {
      const vertex = stack.pop()!;
      if (!BGroupVertices.has(vertex)) {
        BGroupVertices.add(vertex);
        for (const face of edgeFaces) {
          if (face.includes(vertex)) {
            for (const v of face) {
              if (twoVertexIsEdgeVertices.includes(v) && !BGroupVertices.has(v)) {
                stack.push(v);
              }
            }
          }
        }
      }
    }
  }

  let newAGroupVertices = new Set(AGroupVertices);
  let newBGroupVertices = new Set(BGroupVertices);
  // edgeVertices 정점 인덱스 중에서 각 group에 추가할 vertex 설정
  for (const face of edgeFaces) {
    const otherVertices = face.filter(v => !vertexIdxList.includes(v));
    const AGroupFaceVertices = face.filter(v => AGroupVertices.has(v));
    const BGroupFaceVertices = face.filter(v => BGroupVertices.has(v));
    if (AGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!AGroupVertices.has(v)) {
          newAGroupVertices.add(v);
        }
      }
    }
    if (BGroupFaceVertices.length > 0) {
      for (const v of otherVertices) {
        if (!BGroupVertices.has(v)) {
          newBGroupVertices.add(v);
        }
      }
    }
  }
  // 추가된 vertex 반영
  newAGroupVertices.forEach(vertex => AGroupVertices.add(vertex));
  newBGroupVertices.forEach(vertex => BGroupVertices.add(vertex));

  // A group faces와 B group faces 설정
  let AGroupFaces: [number, number, number][] = [];
  let BGroupFaces: [number, number, number][] = [];
  for (const face of edgeFaces) {
    if (face.some(v => AGroupVertices.has(v))) {
      AGroupFaces.push(face);
      continue;
    }
    if (face.some(v => BGroupVertices.has(v))) {
      BGroupFaces.push(face);
      continue;
    }
  }

  // vertexIdxList에 해당하는 vertex들 만큼 mesh index의 새로운 index로 추가하고 geometry attribute 업데이트
  const newVertices: number[] = [];
  const positionAttribute = mesh.geometry.attributes.position;
  const originalVertexCount = positionAttribute.count;

  for (const idx of vertexIdxList) {
    const x = positionAttribute.getX(idx);
    const y = positionAttribute.getY(idx);
    const z = positionAttribute.getZ(idx);
    newVertices.push(x, y, z);
  }

  const newVertexCount = newVertices.length / 3;
  const newIndicesMap = new Map<number, number>();
  for (let i = 0; i < newVertexCount; i++) {
    newIndicesMap.set(vertexIdxList[i], originalVertexCount + i);
  }

  const newPositionArray = new Float32Array(positionAttribute.array.length + newVertices.length);
  newPositionArray.set(positionAttribute.array);
  newPositionArray.set(newVertices, positionAttribute.array.length);
  mesh.geometry.setAttribute('position', new THREE.BufferAttribute(newPositionArray, 3));

  // B 그룹 face의 원래 상태를 저장
  const beforeBGroupFaces = BGroupFaces.map(face => [...face] as [number, number, number]);

  // B group face에서 기존에 vertexIdxList의 vertex에 해당되는 부분을 새로 추가한 index로 대체해서 반영
  for (let i = 0; i < BGroupFaces.length; i++) {
    const face = BGroupFaces[i];
    for (let j = 0; j < 3; j++) {
      if (vertexIdxList.includes(face[j])) {
        face[j] = newIndicesMap.get(face[j])!;
      }
    }
  }

  // 원래 faces 배열을 업데이트하여 B group face들의 위치에 대체된 index를 반영
  for (let i = 0; i < faces.length; i += 3) {
    const curFace: [number, number, number] = [faces[i], faces[i + 1], faces[i + 2]];
    const bFaceIndex = beforeBGroupFaces.findIndex(bFace => 
      (bFace[0] === curFace[0] && bFace[1] === curFace[1] && bFace[2] === curFace[2]) ||
      (bFace[0] === curFace[0] && bFace[1] === curFace[2] && bFace[2] === curFace[1]) ||
      (bFace[0] === curFace[1] && bFace[1] === curFace[0] && bFace[2] === curFace[2]) ||
      (bFace[0] === curFace[1] && bFace[1] === curFace[2] && bFace[2] === curFace[0]) ||
      (bFace[0] === curFace[2] && bFace[1] === curFace[0] && bFace[2] === curFace[1]) ||
      (bFace[0] === curFace[2] && bFace[1] === curFace[1] && bFace[2] === curFace[0])
    );

    if (bFaceIndex !== -1) {
      const updatedFace = BGroupFaces[bFaceIndex];
      faces[i] = updatedFace[0];
      faces[i + 1] = updatedFace[1];
      faces[i + 2] = updatedFace[2];
    }
  }

  mesh.geometry.setIndex(new THREE.BufferAttribute(faces, 1));
}

마지막에 B group face의 이전 face에 일치하는 자리에 

대체된 B group face index를 잘 반영한 것을 확인하였는데

 

잘리지 않았다. 전혀 변화가 없다 

왜 이러지? 

 

1681과 2가 같은 자리에 분리된 것은 확인되는데, 

물리적으로 분리가 안되는 건가 

 

모델을 줄이고 확인해봐야할 것 같다..

 

최소화 모델로 문제 디버깅 

4x3형태로 최소화하여 뭐가 문젠지 알아보자

 

이쪽 부분을 자르니까 잘렸어야할 부분이 잘리지 않고 늘어난다?

 

확인해보니 edge cut로직을 한 후에 새로 생긴 인덱스 12,13 vertex가 mesh에 적용되지 않고 처음 위치에 떠있다 

그래도 축소된 모델로 확인해보니 원인을 알 것 같다 

 

edge cutting 로직의 문제

정리하면 일단 edge위 face들과 기존 vertex는 물리적으로는 constraint가 없어져서 떨어진 것 같다 

하지만 geometry에서는 연결되어있다

 

끊어졌지만, face에서는 제대로 반영되지 않는 것 같다 

그리고 새로 만들어진 vertex 2개 12,13의 경우 mesh로써 작용하지 못하고 face 연결도 제대로 되어있지 않다 

 

A,B group face를 보면 face grouping은 잘되어있다

이제 face가 edge cutting으로 인해 잘 바뀌는지 확인해야한다 

 

잘 바뀌는것 같은데...

변경되는 세 face들을 확인해봐도 모두 잘 변경된다 

 

새로운 vertex 두 개도 -1,0,0  0,0,0 두 개가 geometry position에서는 잘 추가되었다

근데 왜 안되지? 

 

이걸 보고 있으니 실제로 12,13번 vertex는 움직이고 있었다

그 즉슨 위쪽 face에 잘 연결되어서 시뮬레이션까지 되고 있는 걸 알 수 있었다

 

그럼 시뮬레이션에 반영은 되는데 rendering 되는 mesh에서 분리가 안된 것 같다

밑에 주욱 늘어진 것이 원래 위치에 있던 2,3번 vertex로 edge 밑쪽 face에 그대로 붙어있고, 위와는 잘려서 떨어진 것이다 

 

그니까 자르기가 사실 성공한 건데 wireframe으로 볼 때는 아닌 것이다 

이건 어떻게 처리하지?

 

혹시나 해서 wireframe을 꺼봤다 근데

오!

잘렸다 잘렸어 

 

wireframe일 때는 mesh의 처음 정보만을 반영하고 업데이트가 안되어서 그런거였다

실제로 face를 렌더링해보니 잘 잘린 모습이 보인다 

 

주욱 길게 잘라보니 잘 잘린다 

잘려서 새로 생긴 vertex의 경우 face normal이 적용이 안되어있긴 하지만, 일단 성공이다 

 

부족한 점이 있다면 예상대로 직선이 아니라 경로를 어지럽게 자르게 되면 의도한대로 잘 잘리지는 않는다 

 

그럼 이제 이렇게 딱 반으로 자르게 되었을 때 mesh가 분리될 수 있도록 해보면 좋을 것 같다 

 

일단 완벽한 기능을 목표로 하는 것보단 구현 자체에 의의를 두고 싶다 

mesh cutting과 같은 기능도 지금은 버그도 있고, edge를 따라 자른다는 불완전한 구현으로 되어있다

 

하지만 cloth를 잘라서 mesh를 분리하고 다른 cloth를 추가해서 붙여서 연결해보고 등의 기능들을 구현해보면, 

그 다음에 여유가 될 때 논문 등 더 나은 기법으로 수정해보도록 하자

 

 

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