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

Threejs Cloth Tailor 개발일지 - (issue) merge geometry 시뮬레이션 성능 저하, merge geometries 테스트, self collision 성능 저하 원인, merge geometry 성능 저하 결론

728x90
반응형

 

 

(issue) merge geometry 시뮬레이션 느려짐

테스트를 간단한 geometry에서만 해서 그런가. 

geometry를 merge하게 되면 시뮬레이션에서 너무 느려졌다. 프레임이 엄청 끊긴다.

 

원인이 뭐지? mesh를 분리하지 않고 expand vertex를 한 경우에는 괜찮은데, 

merge geometry를 하게 되면 이렇게 느려진다. 

 

constraint를 하나씩 지워보면서 확인해보니 느려지는 원인은 self collision에 있었다. 

geometry merge와 self collision이 무슨 관계이길래 이렇게 느려지는 걸까. 

 

merge geometry방법이 잘못된 걸까..? 

 

merge geometries 테스트 

위와 같은 코드로 테스트를 해봤는데

결국 merge geometries를 통해 합쳐진 mesh를 반영하면 성능이 급격히 저하된다. 

 

이 성능 저하치는
particle 개수가 많아질 수록
더욱 낮아지는 경향이 있었다.

 

self collision 원인 예측 

하.. geometry merge utility가 잘못된 거라면, merge geometry 방법을 직접 attribute 안의 array들을 수정하는 방법으로 시도하면 된다.

일단 collision 코드를 보면서 원인을 예측해보자. 

 

흠... 코드를 봐도 예측이 잘 안된다.

 

일단 다른 방법으로 mergeAttributes를 사용해보자. 

    const mergedPosition = utils.mergeAttributes([geom1.getAttribute("position") as THREE.BufferAttribute, geom2.getAttribute("position") as THREE.BufferAttribute]);
    const mergedNormal = utils.mergeAttributes([geom1.getAttribute("normal") as THREE.BufferAttribute, geom2.getAttribute("normal") as THREE.BufferAttribute]);
    const mergedUv = utils.mergeAttributes([geom1.getAttribute("uv") as THREE.BufferAttribute, geom2.getAttribute("uv") as THREE.BufferAttribute]);

    // get index2 after merge
    const geom1IndexCnt: number = Math.max(...Array.from(geom1.index.array)) + 1
    const mergedVertexIndex2 = vertexIndex2 + geom1IndexCnt;

    // index face list에서 merged vertex index 2에 해당하는 인덱스를 vertex index 1으로 대체 
    if(!geom1.index)
    {
      console.error("merged geometry index is none.");
      return false;
    }
    const newIndex = geom1.index.array.map(index=>{
      if(index === mergedVertexIndex2)
        return vertexIndex1!
      else
        return index 
    })
    geom1.setIndex(Array.from(newIndex))

    // geom1에 attributes 반영
    geom1.setAttribute('position', mergedPosition);
    geom1.setAttribute('normal', mergedNormal);
    geom1.setAttribute('uv', mergedUv);

    // merged vertex index 2가 모두 대체되었는지 확인
    const result = !geom1.index.array.includes(mergedVertexIndex2)
    geom1.computeVertexNormals()
    geom1.attributes.position.needsUpdate = true;

    // 남은 mesh 제거
    scene.remove(mesh2)

    return result
  }

 

아... mesh 분리를 하고 expand vertex 기능을 수행하니까, 두 번째 mesh가 사라진다.

expand vertex 기능은 그렇다 치더라도, merge geometry만이라도 제대로 된다면

constraint를 이용한 attach 기능을 작동시킬 수 있을텐데 말이다. 

 

    const mergedPosition = utils.mergeAttributes([geom1.getAttribute("position") as THREE.BufferAttribute, geom2.getAttribute("position") as THREE.BufferAttribute]);
    const mergedNormal = utils.mergeAttributes([geom1.getAttribute("normal") as THREE.BufferAttribute, geom2.getAttribute("normal") as THREE.BufferAttribute]);
    const mergedUv = utils.mergeAttributes([geom1.getAttribute("uv") as THREE.BufferAttribute, geom2.getAttribute("uv") as THREE.BufferAttribute]);

    // get index2 after merge
    const geom1IndexCnt: number = Math.max(...Array.from(geom1.index.array)) + 1
    const mergedIndex = [ 
      ...geom1.index.array,
      ...geom2.index.array.map(index=>{
        return index + geom1IndexCnt;
      })
    ];
    geom1.setIndex(new THREE.BufferAttribute(new Uint32Array(mergedIndex), 1))

    // // index face list에서 merged vertex index 2에 해당하는 인덱스를 vertex index 1으로 대체 
    // if(!geom1.index)
    // {
    //   console.error("merged geometry index is none.");
    //   return false;
    // }
    // const newIndex = geom1.index.array.map(index=>{
    //   if(index === mergedVertexIndex2)
    //     return vertexIndex1!
    //   else
    //     return index 
    // })
    // geom1.setIndex(Array.from(newIndex))

    // geom1에 attributes 반영
    geom1.setAttribute('position', mergedPosition);
    geom1.setAttribute('normal', mergedNormal);
    geom1.setAttribute('uv', mergedUv);

    // merged vertex index 2가 모두 대체되었는지 확인
    // const result = !geom1.index.array.includes(mergedVertexIndex2)
    // geom1.computeVertexNormals()
    // geom1.attributes.position.needsUpdate = true;

    // 남은 mesh 제거
    scene.remove(mesh2)

    return false

위와 같이 attributes들과 set index로 mesh를 병합하여 테스트해보니 

 

mesh2를 제거하였는데도 자른 조각이 남아있고, 왼쪽 위 hierarchy에 cloth1만 있다는 것은

정상적으로 병합이 되긴되었다.

하지만 여전히 성능이 너무 저하되었다.

 

이건 영상을 찍고 몇 배속이나 증가시켜 뽑아낸 것이다.

실제 시간대비 시뮬레이션 연산이 느리다는 것은 바람의 영향이 많이 줄었다는 면에서 확인할 수 있다. 

 

merge geometry 성능 저하 결론

아.. 결국 성능 저하의 정확한 원인을 찾지는 못했다.

병합 자체가 성능저하의 원인이 되는 것 같은데. 

 

일단 성능 저하에 대해서는 보류한 상태로 constraint에 기반한 attach 기능을 개발하자.

퍼포먼스가 떨어지는 것이지 시뮬레이션 연산 오류가 생기는 것은 아니기 때문에 실현은 가능하다. 

 

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