본문 바로가기

Nature of Code

벡터 기본 방향과 크기


벡터란 크기와 방향을 가지는 객체를 의미

일반적으로 벡터는 화살표를 나타내며 이 화살표의 방향은 벡터의 방향이고

화살표의 길이가 벡터의 크기를 뜻한다.

 

덧셈

다음위치 = 현재 위치 + 속도

백터의 덧셈에서는 기본적으로 벡터 또는 스칼라를 더한다

벡터는 위에 설명한 객체를 의미하며 스칼라는 정수 또는 실수를 의미한

원을 0,0에서 벡터의 방향으로 이동하려면 x : 3 y:4 를 더하면 해당 위치로 이동한다

이것이 벡터가 방향을 가지고 있음을 의미하며 add함수를 쓰는 이유이다.

this._cube.position.add(this._location);
 

뺄셈

그러나 여기서 큐브가 이동하는 방향을 어떻게 구현할 것인가

그럴때 사용하는 것이 뺄셈이다.

현재 마우스 위치에서 첫 마우스 위치를 빼면 벡터의 방향을 구하는 것 가능하다.

마우스를 클릭하면 큐브가 생성대고 그 벡터에 현재 마우스가 위치한 벡터를 빼면 큐브가 이동할 방향을 구할 수 있다. 위의 사진은 +방향으로 x축으로 몇 y축으로 이동할 것이고 반대라면 - 방향으로 x축과 y축으로 이동하기에 왼쪽 아래로 큐브가 이동한다.

 
            this._velocity.add(this._mouse.clone().sub(this._center));
 

 

정규화

그러나 여기서 문제가 생긴다 우리는 큐브를 해당 방향으로 이동하기를 원하는데 만약 x와 y의 값이 매우 높다고하면 문제가 생길것이다 아래와 같이

 

큐브가 매우 빨리 이동한다. 이때 사용하는것이 정규화이다.

정규화란 표준적인 것으로 만드는 것을 의미하며 표준적인 벡터는 단위벡터 이며 길이가 1인 벡터를 의미한다고 한다.

방향을 구할때 정규화를 사용하면 정규화를 사용시 1보다 작고 -1보다는 값이 크게 되어 벡터 연산을 할 때 안정성을 보장한다.

그러나 길이가 0인경우는 정규화가 불가능하니 따로 예외처리를 해줘야 한다.

 

 

아까는 너무 빨라서 안보였다면 지금은 아무리 커도 움직이는것이 보인다.

this._mouse.clone().sub(this._center).normalize()
 

 

벡터의 곱셈은

일반적으로 크기 변환 연산을 의미 방향을 유지한채로 이동을 빠르거나 느리게 하려면 0.001~0.9사이의 값을 곱하면 된다.

이것이 가속도이다.

그리고 벡터를 곱할때는 벡터끼리 곱하지 않고 스칼라와 곱한다.

물론 크기를 절반을 하고 싶은경우 0.5를 곱할 수 있지만 div로 2를 나눠도 된다.

 

벡터의 크기를 구할때는 벡터를 직각삼각형으로 나타내면 벡터는 빗변이된다. 거기서 피타고라스 정리를 이용해

x*2 + y*2 => 벡터의 크기가 된다.

이 벡터의 크기를 이용해서 가속도를 구현하였다.

나는 벡터를 박스가 이동하는 속도를 구현하기 위해 사용하였으며 선의 길이를 구한다음 해당선 길의 0.05로 곱했다.

0.05를 곱한이유는 1보다 작게 하기위해서 이다.

     this._length = this._center.distanceTo(this._mouse);
 
  this._location.multiplyScalar(this._length * 0.05);
 
 

생성자

생성자는 클래스의 특별한 함수로 자신을 인스턴스로 만들때 사용 그리고 new라는 연산자로 호출

        const scene = new THREE.Scene();
        /**필드화 시킴 */
        this._scene = scene;
        /**큐브 위치 */
        this._location = new THREE.Vector3(0, 0, 0);
        /**location에 더할 변수 가속도 */
        this._velocity = new THREE.Vector3(0, 0, 0);
        /**특정 위치에서 다른 위치로 향하게 하는 변수 */
        this._dir = new THREE.Vector3(0, 0, 0);

        /**마우스 위치 */
        this._mouse = new THREE.Vector3(0, 0, 0);
        /**큐브 생성 위치 */
        this._center = new THREE.Vector3(0, 0, 0);
 

 

static

마우스를 향하는 가속도를위한 함수

add는 새로운 객체를 만들어서 반환하지 않고 자기 자신의 값을 변화한다. 그렇기 가속도로는 부적합 하다.

그 후 길이값을 그냥 더하면 엄청난 속도로 이동하기에 정규화를 한 이후 그 값을 곱하면 가속도를 위한 원하는 벡터로 만들 수 있다.

자기 자신의 값을 변화하지 않고 사용하려면 어떻게 할까? threejs에서는 clone() 이라는 함수가 있다.

https://threejs.org/docs/#api/en/core/Object3D.clone

 

three.js docs

 

threejs.org

 

Three.js의 clone() 메서드는 객체의 복사본을 생성하여 원본 데이터에는 영향을 주지 않는다.

       console.log(this._mouse);
            this._dir = this._mouse.sub(this._center).normalize();
            console.log(this._mouse);
 

클론 미사용

값이 바뀌어 있다.

      console.log(this._mouse);
            this._dir = this._mouse.clone().sub(this._center).normalize();
            console.log(this._mouse);
 

클론 사용

원본 데이터 유지

이제 해당 값들을 이용하여 update함수에 적용하자

     this._dir = this._mouse.clone().sub(this._center).normalize(); 
            this._length = this._center.distanceTo(this._mouse);
            this._velocity.add(this._dir);
 

벡터의 방향과 벡터의 크기를 구한다음

update 함수에서 사용

    update(time) {
        if (this._isCube) {
            time *= 0.001;
            this._cube.rotation.x = time;
            this._cube.rotation.y = time;

            /**큐브가 이동할 위치 */
            this._location.add(this._velocity);
            /**선 길에따른 속도 */
            this._location.multiplyScalar(this._length * 0.05);

            /**큐브가 this._location방향으로 이동 set을사용하면 순간이동하니 add로 하나씩 더해서  */
            this._cube.position.add(this._location);
        }
    }
 

마지막으로 경계에 부딛혔을때 튕겨져 나오는 조건 추가

   // 화면 경계에 부딪혔을 때
            const boundaryX = this._divContainer.clientWidth / 250;
            const boundaryY = this._divContainer.clientHeight / 250;

            if (
                this._cube.position.x > boundaryX ||
                this._cube.position.x < -boundaryX
            ) {

                // x 이동 방향 반전
                this._velocity.x *= -1;
            }
            if (
                this._cube.position.y > boundaryY ||
                this._cube.position.y < -boundaryY
            ) {


                // y 이동 방향 반전
                this._velocity.y *= -1;
            }
 

여기서 문제 발생

박스 위치가 경계값을 벗어나는 경우가 생기면 그자리에서 멈추는 이슈 발생 x축 경계가 10 과 -10이라면

11 , -11등 이런식으로 값이 변경되서 안튕김

    if (
                this._cube.position.x > boundaryX ||
                this._cube.position.x < -boundaryX
            ) {
                // 큐브가 화면 경계 내에서만 이동하도록 제한 해당코드 없으면 큐브가 어느순간 멈춤
                this._cube.position.x = Math.min(
                    boundaryX,
                    Math.max(-boundaryX, this._cube.position.x)
                );

                // x 이동 방향 반전
                this._velocity.x *= -1;
            }
            if (
                this._cube.position.y > boundaryY ||
                this._cube.position.y < -boundaryY
            ) {
                // 큐브가 화면 경계 내에서만 이동하도록 제한  해당코드 없으면 큐브가 멈춤
                /**이 부분은 큐브의 y 위치가 위 경계보다 커지지 않도록 보정하는 역할
                 *  this._cube.position.y가 boundaryY보다 크면, boundaryY 가 반환되어
                 *  큐브의 y 위치가 boundaryY보다 커지지 않도록 보장*/
                this._cube.position.y = Math.min(
                    boundaryY,
                    /**y 위치가 아래 경계보다 작아지지 않도록 보정하는 역할 */
                    /**this._cube.position.y가 -boundaryY보다 작으면,
                     * -boundaryY가 반환되어
                     * 큐브의 y 위치가 -boundaryY보다 작아지지 않도록 보장 */
                    Math.max(-boundaryY, this._cube.position.y)
                );

                // y 이동 방향 반전
                this._velocity.y *= -1;
            }
 

min max를 이용해서 x축과 y축 경계를 넘지 않게 설정!

 

 

완료~!



'Nature of Code' 카테고리의 다른 글

Nature of Code 3강. 진동.  (0) 2024.06.11
벡터 힘,질량,중력  (0) 2024.06.09
Nature of Code 2강. 힘.  (0) 2024.05.15
Nature of Code 1강. 벡터.  (1) 2024.05.07