๐Ÿ‘จโ€๐Ÿ’ป Seungineer's GitHub Contribution

๐Ÿงญ KAIST JUNGLE/HandTris

[HandTris] #4. ์›น์บ  ํ™”๋ฉด์„ ๊ฐ€๋ ค ๋ณด์ž - (์† ๋™์ž‘์œผ๋กœ ํ•˜๋Š” ์˜จ๋ผ์ธ ์›น ํ…ŒํŠธ๋ฆฌ์Šค ๊ฒŒ์ž„ ๋งŒ๋“ค๊ธฐ)

seungineer = seungwoo + engineer 2024. 6. 30. 03:11

2024.06.24 - [๐Ÿงญ KAIST JUNGLE/HandTris] - [HandTris] #3. TypeError: Cannot read properties of undefined - (์† ๋™์ž‘์œผ๋กœ ํ•˜๋Š” ์˜จ๋ผ์ธ ์›น ํ…ŒํŠธ๋ฆฌ์Šค ๊ฒŒ์ž„ ๋งŒ๋“ค๊ธฐ)

 

[HandTris] #3. TypeError: Cannot read properties of undefined - (์† ๋™์ž‘์œผ๋กœ ํ•˜๋Š” ์˜จ๋ผ์ธ ์›น ํ…ŒํŠธ๋ฆฌ์Šค ๊ฒŒ์ž„ ๋งŒ

socket์˜ url์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋‹ค.soccket ๋ณ€์ˆ˜์— ๋‹ด๊ฒจ ์žˆ๋Š” url ์†์„ฑ์„ ๊ฐ€์ ธ์™€ sessionId๋ฅผ parsing ํ•˜๊ณ ์ž ํ•˜๋˜ ์ค‘ ๋งŒ๋‚ฌ๋˜ ์—๋Ÿฌ ์ค‘ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์ง€ ์•Š์•„ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜๊ณ ์ž ํ•œ๋‹ค. ์ œ๋ชฉ์€ 'Typ

seungineer.tistory.com

๊ฐœ๋ฐœ ์ค‘์ธ ํ•ธ๋“œํŠธ๋ฆฌ์Šค๊ฐ€ toy project ์ˆ˜์ค€์ด๋ผ๋Š” ๋Š๋‚Œ์„ ๋ฒ„๋ฆด ์ˆ˜ ์—†์—ˆ๋‹ค. ์–ด๋–ค ์š”์†Œ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”์ง€ ๊ณฐ๊ณฐ์ด ์ƒ๊ฐํ•ด ๋ณด๋‹ˆ ์›น์บ  ํ™”๋ฉด์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ํ˜„์žฌ ํ•ธ๋“œํŠธ๋ฆฌ์Šค๋Š” ์›น์บ ์— ๋น„์น˜๋Š” ํ”Œ๋ ˆ์ด์–ด์˜ ํ™”๋ฉด์ด ์™ผ์ชฝ ์ƒ๋‹จ์— ๋ณด์ด๋Š” ํ˜•ํƒœ์ด๋‹ค. ์† ๋™์ž‘์ด ์›น์บ ์— ์ž˜ ๋น„์น˜๊ณ  ์žˆ๋Š”์ง€ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํ™•์ธํ•ด์•ผ ํ•˜๊ธฐ์— ๋น„์น˜๋Š” ํ™”๋ฉด์ด ๋ณด์ด๋Š” ๊ฒŒ ํ•„์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์–ด๋–ค ์บ ์„ ์ด์šฉํ•œ ๊ฒŒ์ž„๋„ ์›น์บ ์˜ ํ™”๋ฉด์ด ๊ทธ๋Œ€๋กœ ๋‚˜์˜ค์ง€๋Š” ์•Š๋Š”๋‹ค๋Š” ์ ์„ ๊นจ๋‹ซ๊ฒŒ ๋˜์—ˆ๋‹ค. ์›น์บ  ํ™”๋ฉด์„ ๊ฐ€๋ ค์•ผ ํ•˜๋Š” ์ด์œ ๊ฐ€ ์ƒ๊ฒผ๋‹ค.

์ขŒ์ธก ์ƒ๋‹จ์— ์›น์บ  ํ™”๋ฉด์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

ํ”ผํŠธ๋‹ˆ์Šค ๋ณต์‹ฑ2(์ขŒ), ํ”ผํŠธ๋‹ˆ์Šค ๋Ÿฌ๋„ˆ(์šฐ) ๋“ฑ ์บ ์„ ์ด์šฉํ•œ ๊ฒŒ์ž„์— ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ๋ณด์ด์ง€ ์•Š์Œ


Three.js logo

Three.js

์›น์บ  ํ™”๋ฉด์„ ๊ฐ€๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ ๊ฐ€์žฅ ๋จผ์ € ๋“  ์ƒ๊ฐ์€ ์†๊ฐ€๋ฝ์— ์ž…์ฒด ์žฅ๊ฐ‘์„ ์”Œ์šฐ๋Š” ๊ฒƒ์ด๋‹ค. ์žฅ๊ฐ‘๋งŒ ๋ณด์ด๊ณ , ํ”Œ๋ ˆ์ด์–ด ๋ชจ์Šต์„ ๊ฐ€๋ฆด ์ˆ˜ ์žˆ๊ธฐ์— ํ”Œ๋ ˆ์ด์–ด๋Š” ์ž์‹ ์˜ ์†์ด ์ž˜ ์ธ์‹๋˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. Mini Milestone์„ Three.js๋กœ ์†์„ ๋„์šฐ๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ์žก์•˜๋‹ค. Three.js๋Š” x, y, z ์„ธ ๊ฐœ์˜ ์ถ•๊ณผ camera view, ๊ทธ๋ฆฌ๊ณ  obj, stl ๋“ฑ๊ณผ ๊ฐ™์€ 3D ๋ชจ๋ธ๋ง ํŒŒ์ผ์ด ํ•„์š”ํ•˜๋‹ค. ์šฐ์„  ์ ์œผ๋กœ๋งŒ ์ด๋ฃจ์–ด์ง„ .obj ํŒŒ์ผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์•˜๋‹ค.

์Šคํฌ๋ฆฐ์ƒท ์šฐ์ธก์— ์ ์œผ๋กœ๋งŒ ์ด๋ฃจ์–ด์ง„ obj ํŒŒ์ผ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Three.js๋กœ  ์ด๋ฅผ ๋ Œ๋”ํ•œ ๊ฒฐ๊ณผ ์›น์˜ ์ฐฝ ์† three.js canvas์™€ ๊ฐ™์ด ์ ๋“ค์ด ์ฐํ˜”๋‹ค(์šฐ์ธก ์ƒ๋‹จ์˜ ์•„์ฃผ ์ž‘์€ ํฐ ์ ). ์ด ์ ๋“ค์„ ์†์˜ ๋งˆ๋””์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ์›€์ง์ด๊ฒŒ ํ•ด์ค˜์•ผ ํ–ˆ๋‹ค. Mediapipe component์˜ landmark(์†์˜ ๋งˆ๋”” ์œ„์น˜) ์ƒํƒœ๋ฅผ Three.js ์ปดํฌ๋„ŒํŠธ๋กœ props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•˜์—ฌ, Three.js์—์„œ landmark ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜๋„๋ก ํ•˜์˜€๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์†์ด ์›€์ง์ผ ๋•Œ๋งˆ๋‹ค ๋žœ๋“œ๋งˆํฌ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜์—ฌ Three.js ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

21๊ฐœ์˜ ์ ์ด ์†์˜ ์œ„์น˜์— ๋”ฐ๋ผ ์›€์ง์ด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ ๋งŒ ์žˆ๋Š” obj ํŒŒ์ผ์— ์„ ์„ ์ถ”๊ฐ€ํ•˜์—ฌ three.js ์ƒ์˜ ์†์— ์„ ์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

๋”๋ณด๊ธฐ

๐Ÿ“ .obj ํŒŒ์ผ ๋ณด๊ธฐ

      # ๋ฌผ์ฒด ์ด๋ฆ„
      o Hand
      # ๋งˆ๋””
      v 0.0 0.0 0.0
      v 0.0 1.0 0.0
      v 0.0 2.0 0.0
      v 0.0 3.0 0.0
      v 0.0 4.0 0.0
      v 1.0 1.0 0.0
      v 1.0 2.0 0.0
      v 1.0 3.0 0.0
      v 1.0 4.0 0.0
      v 2.0 0.0 0.0
      v 2.0 1.0 0.0
      v 2.0 2.0 0.0
      v 2.0 3.0 0.0
      v 3.0 0.0 0.0
      v 3.0 1.0 0.0
      v 3.0 2.0 0.0
      v 3.0 3.0 0.0
      v 4.0 0.0 0.0
      v 4.0 1.0 0.0
      v 4.0 2.0 0.0
      v 4.0 3.0 0.0
      v 5.0 0.0 0.0
      v 5.0 1.0 0.0
      v 5.0 2.0 0.0
      v 5.0 3.0 0.0
      # ์„ 
      l 1 2
      l 2 3
      l 3 4
      l 4 5
      l 2 6
      l 6 7
      l 2 10
      l 10 11
      l 11 12
      l 12 13

์ด๋ ‡๊ฒŒ Mini Milestone์€ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์—ฌ๊ธฐ์„œ .obj ํŒŒ์ผ์— ์†๊ฐ€๋ฝ ํ˜•ํƒœ๋ฅผ ์ž…ํ˜€์ค˜์•ผ ํ–ˆ์œผ๋‚˜ ์ด๋Š” 3D ๋ชจ๋ธ๋ง์˜ ์˜์—ญ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋ธ์˜ ์–ด๋–ค ์ง€์ ๊ณผ ์†์˜ ์–ด๋–ค ์ง€์ ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กœ์šด ์ผ์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

๐Ÿ•น๏ธ ํ•ธ๋“œ์กฐ์ด์Šคํ‹ฑ

๊ธฐ์กด ์†๊ฐ€๋ฝ ํ˜•ํƒœ๋ฅผ ์ธ์‹ํ•ด ํ…ŒํŠธ๋ฆฌ์Šค ๋ธ”๋Ÿญ์„ ์กฐ์ž‘ํ•˜๋˜ ๊ฒƒ์„ ์ค‘๊ฐ„๋ฐœํ‘œ ์ดํ›„ ํ•ธ๋“œ ์กฐ์ด์Šคํ‹ฑ ํ˜•ํƒœ๋กœ ์ „ํ™˜ํ•˜๊ณ ์ž ํ•˜์˜€๋‹ค. ์ด์— ์กฐ์ด์Šคํ‹ฑ ํ˜•ํƒœ์˜ 3D Object๋ฅผ ์†์˜ ์›€์ง์ž„์— ๋”ฐ๋ผ ์ด๋™ํ•˜๊ฒŒ ํ•˜๋ฉด, ์•ž์„œ ์„ธ์› ๋˜ ์›น์บ ์„ ๊ฐ€๋ฆฌ์ž๋Š” ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์†์˜ landmark ์ •๋ณด๋ฅผ three.js์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๊ธฐ์— ์‹คํ˜„ ๊ฐ€๋Šฅํ•  ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ–ˆ๋‹ค.

๐Ÿ› ๋ชจ๋ธ๋ง ํŒŒ์ผ ๋กœ๋“œ ์‹œ camera view ๋ฌธ์ œ

์กฐ์ด์Šคํ‹ฑ ํ˜•ํƒœ์˜ .obj ํŒŒ์ผ์„ three.js์— load ํ•˜์˜€๋‹ค. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ load ํ•œ ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ–ˆ์œผ๋‚˜ three.js canvas์—๋Š” ์–ด๋–ค ๊ฒƒ๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š์•˜๋‹ค.

ํ……~ scene์— ์ถ”๊ฐ€ํ•œ axes helper๋งŒ ๋ณด์ž„

Three.js์— ์ต์ˆ™ํ•˜์ง€ ์•Š์•„ load์˜ ์˜ค๋ฅ˜์ธ์ง€, object ํŒŒ์ผ์ด ์ž˜๋ชป๋œ ๊ฒƒ์ธ์ง€, ํ‘œ์‹œ๋˜๊ณ  ์žˆ๋Š”๋ฐ ์•„์ฃผ ์ž‘๊ฒŒ ๋‚˜์˜ค๊ณ  ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. load๋Š” ์•ž์„œ Mini Milestone์œผ๋กœ ์ •ํ•œ ๊ณผ์ œ๋ฅผ ํ•˜๋ฉฐ ํ…Œ์ŠคํŠธํ–ˆ์—ˆ๊ณ , object ํŒŒ์ผ๋„ obj ๋ทฐ์–ด๋กœ ์—ด์–ด๋ณด๋‹ˆ ์ž˜ ์—ด๋ ธ๋‹ค.  load๋Š” ๋˜๋Š”๋ฐ, ๋‚ด๊ฐ€ ๋ณด๋Š” ์‹œ์ ์— ์—†๋Š” ๊ฒƒ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

์–ด๋–ค object ํŒŒ์ผ์ด๋”๋ผ๋„ ์ตœ์ดˆ load ์‹œ ๋ฌผ์ฒด๊ฐ€ ๋ณด์ผ ์ˆ˜ ์žˆ๊ฒŒ camera view๋ฅผ ์กฐ์ •ํ•ด ์ฃผ์—ˆ๋‹ค.

      if (!cameraAdjusted) {
        const box = new THREE.Box3().setFromObject(joystick);
        const boxSize = box.getSize(new THREE.Vector3()).length();
        const boxCenter = box.getCenter(new THREE.Vector3());
        
        const halfSizeToFitOnScreen = boxSize * 0.5;
        const halfFovY = THREE.MathUtils.degToRad(cameraRef.current.fov * 0.5);
        const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);

        cameraRef.current.position.copy(boxCenter);
        cameraRef.current.position.z += distance * 1.5; // Add some distance for better view
        cameraRef.current.lookAt(boxCenter);
        cameraRef.current.updateProjectionMatrix();

        setCameraAdjusted(true); // ์นด๋ฉ”๋ผ ์กฐ์ •๋˜์—ˆ์Œ ํ‘œ์‹œ
      }

์กฐ์ด์Šคํ‹ฑ ๋“ฑ์žฅ

์กฐ์ด์Šคํ‹ฑ ํŒ๊ณผ ์กฐ์ด์Šคํ‹ฑ ์†์žก์ด์˜ ๋ถ„๋ฆฌ ํ•„์š”

์œ„ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด ์†์˜ ์›€์ง์ž„์— ๋”ฐ๋ผ ๋ชจ๋ธ์ด ํ•จ๊ป˜ ์›€์ง์ธ๋‹ค. ๋‚ด๊ฐ€ ์˜๋„ํ•œ ๊ฒƒ์€ ์กฐ์ด์Šคํ‹ฑ ํŒ์€ ๊ณ ์ •๋˜์–ด ์žˆ๊ณ , ์กฐ์ด์Šคํ‹ฑ ์†์žก์ด๋งŒ ์›€์ง์ด๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.. ์กฐ์ด์Šคํ‹ฑ์—์„œ ํŒ(Plate)์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ณ ์ •์‹œํ‚ค๊ณ , ์†์žก์ด ๋ถ€๋ถ„์€ ์†์ด ํšŒ์ „ํ•˜๋Š” ๋งŒํผ ํšŒ์ „ํ•˜๋„๋ก ๊ฐœ๋ฐœ ์ „๋žต์„ ๋ฐ”๊พธ์—ˆ๋‹ค.

Sketchup ์Šคํฌ๋ฆฐ์ƒท, ์†์žก์ด๋ฅผ ๋ถ„๋ฆฌํ•œ ๋ชจ๋ธ(์ขŒ) ํ•˜๋‚˜, ํŒ์„ ๋ถ„๋ฆฌํ•œ ๋ชจ๋ธ(์šฐ) ํ•˜๋‚˜

Three.js scene์— plate๋ฅผ ๋จผ์ € add ํ•œ๋‹ค. Plate์˜ x, y, z ์ขŒํ‘œ๋Š” landmark๊ฐ€ ๋ณ€ํ•˜๋”๋ผ๋„ ๊ณ ์ •์‹œํ‚จ๋‹ค.

    // ํŒ
    loader.load(
      objUrlPlate,
      (obj) => {
        obj.traverse((node) => {
          if (node.isMesh) {
            node.material = new THREE.MeshPhongMaterial({
              color: 0xff0000,
              emissive: 0x333333,
            });
          }
        });

        obj.scale.set(0.15, 0.15, 0.15);
        obj.position.set(0, 1, 1);
        scene.add(obj);
        console.log('Joystick model loaded:', obj);
      }

์ดํ›„ scene์— stick์„ addํ•œ๋‹ค. Stick ๋˜ํ•œ x, y, z ์ขŒํ‘œ๋Š” ๋ชจ๋ธ ์ž์‹ ์˜ x, y, z ์ขŒํ‘œ๋ฅผ ๊ฐ–๋„๋ก ํ•œ๋‹ค. plate์™€ ๋‹ค๋ฅธ ์ ์€ landmarks๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ•œ ์†๋ชฉ๊ณผ ์—„์ง€์˜ ๊ฐ๋„๋งŒํผ stick์„ ํšŒ์ „์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

atan2() ํ•จ์ˆ˜๋กœ X์ถ•๊ณผ ์ด๋ฃจ๋Š” ๊ฐ์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Œ

      const deltaZ = landmark3.z - landmark0.z; // ์‚ฌ๋žŒ์˜ ์กฐ์ž‘๊ณผ ์›น์บ ์— ๋ณด์—ฌ์ง€๋Š” ํ™”๋ฉด์˜ ์ฐจ์ด๋กœ์ธํ•ด 3๊ณผ 0์˜ ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฆ„
      const deltaX = landmark0.x - landmark3.x;
      const angle = -Math.atan2(deltaZ, deltaX); // theta, ๋‹จ์œ„: rad

      if (angle > 0.3 && angle < 3.0){ // 17๋„ ์ด์ƒ 171๋„ ์ดํ•˜ ์›€์ง์ž„ ์ œํ•œ
        joystick.rotation.z = angle;
๋๋‹ค!

Three.js ๋ฐฐ๊ฒฝ๋„ ์ง€์šฐ๊ณ , ์นด๋ฉ”๋ผ ๋ทฐ๋„ ์–ด๋Š ์ •๋„ ์† ๋ณด๊ณ , ์ƒ‰๋„ ์ž…ํžˆ๋ฉด ์†์„ ๋”ฐ๋ผ๊ฐ€๋Š” ๊ทธ๋Ÿด์‹ธํ•œ ์กฐ์ด์Šคํ‹ฑ์ด ๋งŒ๋“ค์–ด์งˆ ๊ฒƒ ๊ฐ™๋‹ค๐Ÿค˜. ์ด์ œ ์˜ค๋ฅธ์†์œผ๋กœ ๋ˆ„๋ฅด๋Š” ๋ฒ„ํŠผ๋„ ๋งŒ๋“ค์–ด์•ผ๊ฒ ๋‹ค.

 

์ตœ์ข…๋ฐœํ‘œ D-13