AmazonSumerianで物体をクリックしたらその場所にエンティティを出現させてみる

AmazonSumerianで物体をクリックしたらその場所にエンティティを出現させるができたのでやり方をメモしておく。

## 参考情報

* SumerianのSlackのraycastのサンプル
 * https://amazonsumerian.slack.com/archives/C8AR6KC00/p1533222357000110
* API Reference

## やってみたこと

配置された球をクリックするとその場所にボックスが表示されるようにする。

* Create EntityでBoxを追加する
* 追加したBoxをAssetsにドラッグして追加したBox Entityは削除しておく。
* Create EntityでSphereを追加する
* 追加したSphereのscaleを10あたりにして適当な場所に配置する
* 追加したSphereにCollider Componentを追加してShapeをSphereにしておく。
* 追加したSphereにScript Componentを追加して以下のCustom Scriptを追加する。

```javascript
'use strict';

var setup = function(args, ctx, sumerian) {
	
    cameraAndRaySetup(args, ctx);
    ctx.onMouseDown = function(evt){
		ctx.collisionPoint = undefined; 
        ctx.collisionPoint = getRayCollideFromMouse(args, ctx, evt);  
        if (ctx.collisionPoint != undefined) {
            console.log(ctx.collisionPoint);
			createEntity(args, ctx, ctx.collisionPoint);
		}
    };
	//adds a listener for mouse down
    ctx.domElement.addEventListener('mousedown', ctx.onMouseDown);    
};

function createEntity(args, ctx, point) {
	if (!ctx.entities) {
		ctx.entities = [];		
	}
	
	// ここのコメントを外して下のcloneをコメントアウトすると球を作成するようになる
	/*var blue = new sumerian.Material("Blue", sumerian.ShaderLib.simpleColored);
	blue.uniforms.color = [0, 0, 1];
	var entity = ctx.world.createEntity(new sumerian.Sphere(32, 32), blue, "TestSphere").addToWorld();*/
	
	var entity = sumerian.EntityUtils.clone(ctx.world, args.entity).addToWorld();
	ctx.entities.push(entity);
	entity.setTranslation([point.x, point.y, point.z]);
}

function cleanEntities(ctx) {
	if (!ctx.entities) {
		return;
	}
	
	for (let i=0; i < ctx.entities.length; i++) {
		ctx.world.removeEntity(ctx.entities[i]);
	}
}

function getRayCollideFromMouse(args, ctx, evt){
	
	//reset the result
	ctx.result.reset();
    ctx.x = evt.clientX * ctx.dpr;   
    ctx.y = evt.clientY * ctx.dpr;
    ctx.activeCameraEntity.cameraComponent.camera.getPickRay(ctx.x, ctx.y, ctx.viewportWidth, ctx.viewportHeight, ctx.ray);  
    ctx.physicsSystem.raycastClosest(ctx.ray.origin, ctx.ray.direction, args.maxDistance, {}, ctx.result);
	
    if (ctx.result.entity != null){
        if(ctx.result.entity.hasTag(args.targetTag)){ 
            ctx.resultsFromCollide = ctx.result.point;
			return(ctx.resultsFromCollide);
		}              
	}
	
	else{
		console.log('ray did not hit a enitiy with a collider and a tag labeled' + args.targetTag);
	}   
}
  

var cleanup = function(args, ctx) {
    
	//remove the listener when application stops
    ctx.domElement.removeEventListener('mousedown', ctx.onMouseDown);
	cleanEntities(ctx);
      
};
  
function cameraAndRaySetup(args, ctx){
	
	//the device pixel ratio on you screen
    ctx.dpr = ctx.world.gooRunner.renderer.devicePixelRatio;
     
	//defines a ray
    ctx.ray = new sumerian.Ray();
     
	//defines the physics sytem
    ctx.physicsSystem = ctx.world.getSystem('PhysicsSystem');
    
	//defines the result
    ctx.result = new sumerian.RaycastResult();     
}
 
var parameters = [{
    key: 'maxDistance',
    type: 'float',
    'default': 10000,
    min: 0
},{
    key: 'targetTag',
    type: 'string',
    'default': 'surface'
},{
	type: 'entity',
	key: 'entity', 
	description: 'Entity drop area'
}];
```

 * 上記Scriptのentity parameterにAssetsのBoxをドラッグして指定しておく。
 * 追加したSphereのTagsにsurfaceを追加する。

## はまったこと

* 元のスクリプトだとcameraAndRaySetup関数でctx.activeCameraEntity.cameraComponent.cameraをctx.cameraに保存して利用していたがそうするとカメラをズームしたときにうまくraycastできなかった。
* 追加したentityはeditor上には表示されず削除しておかないとそのまま残り続ける。