#A-Frame
バーチャルリアリティ体験を構築するためのオープンソースのWebフレームワークの一つです。
https://aframe.io
A-FrameのEntity Component SystemのComponentは外観・動作・機能を構築するためにEntity上で組み合わせ・照合・および構成できるJavascriptモジュールです。
JavaScriptでComponentを登録し、DOMから宣言的に使用できます。
Componentは構成可能・再利用可能・および共有可能です。
A-FrameアプリケーションのほとんどのコードはComponent内に存在する必要があります。
ECS(エンティティ・コンポーネント・システム)とは、主にゲーム開発で使用されているソフトウェアアーキテクチャパターンです。ECSは継承よりコンポジションの原則に従うことで、より柔軟にエンティティを定義することを可能にしています。
#カメラをトラッキングするコンポーネントの作成
常にカメラの正面に移動させ、カメラの方向を向かせる機能のコンポーネント(camera-tracking)を作成し、文字とボックスのエンティティに組み込みます。
また、camera-trackingのプロパティとしてカメラからの「半径・X距離・Y距離」を与えることで画面レイアウトをしやすくします。
#コード
###HTML
<html>
<head>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script src="tracking.js"></script>
</head>
<body>
<a-scene>
<!--Camera-->
<a-entity id="camera" camera></a-entity>
<!--Field-->
<a-sky color="#44AAFF"></a-sky>
<a-plane position="0 0 -5" rotation="-90 0 0" width="6" height="6" color="#BB9944" shadow></a-plane>
<!--Camera-tracking Text-->
<a-entity id="text" camera-tracking="circleR: 2; shiftX: 1; shiftY: 0.1"
text="font: mozillavr; value: Tracking test.; color: black"
scale="3 3 1">
</a-entity>
<!--Camera-tracking Box-->
<a-entity id="box" camera-tracking="circleR: 3; shiftX: 0; shiftY: -0.5"
geometry="primitive: box"
scale="0.8 0.3 0.2" material="color: red" shadow>
</a-entity>
</a-scene>
</body>
</html>
###JavaScript
AFRAME.registerComponent('camera-tracking', {
schema: {
circleR: {type: 'float', default: '1'},
shiftX: {type: 'float', default: '0'},
shiftY: {type: 'float', default: '0'}
},
tick: function () {
var camera = document.querySelector('#camera');
var cameraPosition = camera.object3D.position;
var cameraRotation = camera.object3D.rotation;
// center position
var cameraX = cameraPosition.x;
var cameraY = cameraPosition.y;
var cameraZ = cameraPosition.z;
// rotation degree
var degreePit = (cameraRotation.x * 180 / Math.PI);
var degreeYaw = (cameraRotation.y * 180 / Math.PI);
// circle size
var r = this.data.circleR;
// rotation point
var positionY = Math.sin(degreePit / 180 * Math.PI) * r;
var xzr = Math.cos(degreePit / 180 * Math.PI) * r;
var positionX = Math.cos((degreeYaw + 90) / 180 * Math.PI) * xzr;
var positionZ = Math.sin((degreeYaw + 90) / 180 * Math.PI) * -1 * xzr;
// shift x value
var addX = this.data.shiftX;
var addXPosX = Math.sin((degreeYaw + 90) / 180 * Math.PI) * addX;
var addXPosZ = Math.cos((degreeYaw + 90) / 180 * Math.PI) * addX;
// shift y value
var addY = this.data.shiftY;
var addYPosX = Math.sin(degreePit / 180 * Math.PI) * Math.cos((degreeYaw + 90) / 180 * Math.PI) * -1 * addY;
var addYPosY = Math.sin((degreePit + 90) / 180 * Math.PI) * addY;
var addYPosZ = Math.sin(degreePit / 180 * Math.PI) * Math.sin((degreeYaw + 90) / 180 * Math.PI) * addY;
// set properties
this.el.setAttribute('rotation', degreePit +' '+ degreeYaw +' 0');
this.el.setAttribute('position', (positionX + cameraX + addXPosX + addYPosX)+' '+ (positionY + cameraY + addYPosY) +' '+ (positionZ + cameraZ + addXPosZ + addYPosZ));
}
});
#解説