본문 바로가기

Graphics

[playcanvas] Entity 드래그하기

 

마우스로 클릭하고 드래그하는 기능을 구현해보겠습니다.

드래그를 구현하기 위해서 ray란 걸 이용할겁니다.

 

var Raycast = pc.createScript('raycast');

Raycast.attributes.add('cameraEntity', {type: 'entity', title: 'Camera Entity'});
Raycast.attributes.add('dragEntity', {type: 'entity', title: 'Drag Entity'});


Raycast.prototype.initialize = function() {
    this.ray = new pc.Ray();
    
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
    this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    
    // pc.Plane: https://github.com/playcanvas/engine/blob/master/src/shape/plane.js  
    this.plane = new pc.Plane(this.dragEntity.getPosition().clone(), this.dragEntity.up.clone());
};

Raycast.hitPosition = new pc.Vec3();
Raycast.dragPosition= new pc.Vec3();

Raycast.prototype.doRayCast = function (screenPosition) {
    var start = this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.nearClip);
    var destination = this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.farClip);
    this.ray.origin.copy(start);
    this.ray.direction.copy(destination);
    var interesecting = this.plane.intersectsRay(this.ray, Raycast.hitPosition);

    if (interesecting) { // true
        Raycast.dragPosition.sub2(Raycast.hitPosition, this.dragEntity.getPosition());
        Raycast.dragPosition.add(this.dragEntity.getPosition());        
        this.dragEntity.setPosition(Raycast.dragPosition);
    }  
};


Raycast.prototype.onMouseDown = function(event) {
    if (event.button == pc.MOUSEBUTTON_LEFT) {
        this.state = 'dragging';
    }
};

Raycast.prototype.onMouseUp = function(event) {
    this.state = 'stationary';
};

Raycast.prototype.onMouseMove = function(event) {
    if ( this.state == 'dragging' ) {
        this.doRayCast(event);
        
    }
};

 

 

일단 드래그 기능을 구현하고,

1. 판 만들기

Ifinite Plane을 하나 만들어줍니다. up을 이용해 만들기 때문에 0,1,0 인 단위벡터이기때문에 끊없는 바닥이 만들어졌다고 생각하면 됩니다.

만약 this.dragEntity.right 즉, 1,0,0 인 단위벡터를 이요해 만들었으면, 끊없는 벽이 만들어 질겁니다 (Entity 기준). 

this.dragEntity.forward 면 벽이 z 축 기준으로 생성되겠네요

 

하여튼 바닥을 만들었는데, 왜 바닥을 만들었냐면, 이 바닥을 카메라가 보고 있고, 이 카메라에서 ray를 발생시킵니다. 그리고 이 ray가 바닥에 HIT 히트 시킬겁니다. 

그냥 바닥이 아니라 마우스가 클릭된 위치로 레이를 발사할겁니다.

 

2. 레이의 시작, 도착 좌표 구해놓기

일단 발사지점은 마우스의 위치이지만 카메라기준 nearclip로 3D 공간에서의 vec3 좌료를 얻어냅니다. (원래는 x,y 니깐 vec2)

레이의 목적지도 마우스 위치여서 vec2지만 카메라의  farClip기준으로 3차원으로 변환시켜 좌표를 얻습니다. 

nearClip 과 farClip 보기

 

상자의 Y축기준으로 하나 만들어줌

이 무한의 판은 화면전체에서 레이와 충돌인식을 하기 위해 만들어줌

모바일 게임을 할때 손가락으로 할때는 유용하지만 나는 필요없을듯-

 

레이를 발생시키고 판과 레이가 곂치는 부분으로 엔티티를 이동시켜줍니다.

 

 

'Graphics' 카테고리의 다른 글

three.js 와 WebGL 정의  (0) 2019.11.14
V-Ray material to glTF  (0) 2019.11.14
[playcanvas] Entity 드래그하기  (0) 2019.10.07
[math] 벡터의 정규화란  (0) 2019.09.27
[playcanvas] Entity up, right, forward  (0) 2019.09.27
[playcanvas] Entity Picking을 이용해본 Gizmo 형태  (0) 2019.09.26