TransformControlsGizmo constructor
TransformControlsGizmo(
- dynamic controls
Implementation
TransformControlsGizmo(controls) : super() {
this.controls = controls;
// shared materials
var gizmoMaterial = new MeshBasicMaterial({
"depthTest": false,
"depthWrite": false,
"fog": false,
"toneMapped": false,
"transparent": true
});
var gizmoLineMaterial = new LineBasicMaterial({
"depthTest": false,
"depthWrite": false,
"fog": false,
"toneMapped": false,
"transparent": true
});
// Make unique material for each axis/color
var matInvisible = gizmoMaterial.clone();
matInvisible.opacity = 0.15;
var matHelper = gizmoLineMaterial.clone();
matHelper.opacity = 0.5;
var matRed = gizmoMaterial.clone();
matRed.color.setHex(0xff0000);
var matGreen = gizmoMaterial.clone();
matGreen.color.setHex(0x00ff00);
var matBlue = gizmoMaterial.clone();
matBlue.color.setHex(0x0000ff);
var matRedTransparent = gizmoMaterial.clone();
matRedTransparent.color.setHex(0xff0000);
matRedTransparent.opacity = 0.5;
var matGreenTransparent = gizmoMaterial.clone();
matGreenTransparent.color.setHex(0x00ff00);
matGreenTransparent.opacity = 0.5;
var matBlueTransparent = gizmoMaterial.clone();
matBlueTransparent.color.setHex(0x0000ff);
matBlueTransparent.opacity = 0.5;
var matWhiteTransparent = gizmoMaterial.clone();
matWhiteTransparent.opacity = 0.25;
var matYellowTransparent = gizmoMaterial.clone();
matYellowTransparent.color.setHex(0xffff00);
matYellowTransparent.opacity = 0.25;
var matYellow = gizmoMaterial.clone();
matYellow.color.setHex(0xffff00);
var matGray = gizmoMaterial.clone();
matGray.color.setHex(0x787878);
// reusable geometry
var arrowGeometry = new CylinderGeometry(0, 0.04, 0.1, 12);
arrowGeometry.translate(0, 0.05, 0);
var scaleHandleGeometry = new BoxGeometry(0.08, 0.08, 0.08);
scaleHandleGeometry.translate(0, 0.04, 0);
var lineGeometry = new BufferGeometry();
lineGeometry.setAttribute(
'position', new Float32BufferAttribute(Float32Array.from([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]), 3));
var lineGeometry2 = new CylinderGeometry(0.0075, 0.0075, 0.5, 3);
lineGeometry2.translate(0, 0.25, 0);
var CircleGeometry = (radius, arc) {
var geometry =
new TorusGeometry(radius, 0.0075, 3, 64, arc * Math.PI * 2);
geometry.rotateY(Math.PI / 2);
geometry.rotateX(Math.PI / 2);
return geometry;
};
// Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
var TranslateHelperGeometry = () {
var geometry = new BufferGeometry();
geometry.setAttribute(
'position', new Float32BufferAttribute(Float32Array.fromList([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), 3));
return geometry;
};
// Gizmo definitions - custom hierarchy definitions for setupGizmo() function
var gizmoTranslate = {
"X": [
[
new Mesh(arrowGeometry, matRed),
[0.5, 0.0, 0.0],
[0.0, 0.0, -Math.PI / 2]
],
[
new Mesh(arrowGeometry, matRed),
[-0.5, 0.0, 0.0],
[0.0, 0.0, Math.PI / 2]
],
[
new Mesh(lineGeometry2, matRed),
[0.0, 0.0, 0.0],
[0.0, 0.0, -Math.PI / 2]
]
],
"Y": [
[
new Mesh(arrowGeometry, matGreen),
[0, 0.5, 0]
],
[
new Mesh(arrowGeometry, matGreen),
[0, -0.5, 0],
[Math.PI, 0, 0]
],
[new Mesh(lineGeometry2, matGreen)]
],
"Z": [
[
new Mesh(arrowGeometry, matBlue),
[0, 0, 0.5],
[Math.PI / 2, 0, 0]
],
[
new Mesh(arrowGeometry, matBlue),
[0, 0, -0.5],
[-Math.PI / 2, 0, 0]
],
[
new Mesh(lineGeometry2, matBlue),
null,
[Math.PI / 2, 0, 0]
]
],
"XYZ": [
[
new Mesh(new OctahedronGeometry(0.1, 0), matWhiteTransparent.clone()),
[0, 0, 0]
]
],
"XY": [
[
new Mesh(
new BoxGeometry(0.15, 0.15, 0.01), matBlueTransparent.clone()),
[0.15, 0.15, 0]
]
],
"YZ": [
[
new Mesh(
new BoxGeometry(0.15, 0.15, 0.01), matRedTransparent.clone()),
[0, 0.15, 0.15],
[0, Math.PI / 2, 0]
]
],
"XZ": [
[
new Mesh(
new BoxGeometry(0.15, 0.15, 0.01), matGreenTransparent.clone()),
[0.15, 0, 0.15],
[-Math.PI / 2, 0, 0]
]
]
};
var pickerTranslate = {
"X": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0.3, 0, 0],
[0, 0, -Math.PI / 2]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[-0.3, 0, 0],
[0, 0, Math.PI / 2]
]
],
"Y": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0.3, 0]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, -0.3, 0],
[0, 0, Math.PI]
]
],
"Z": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0, 0.3],
[Math.PI / 2, 0, 0]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0, -0.3],
[-Math.PI / 2, 0, 0]
]
],
"XYZ": [
[new Mesh(new OctahedronGeometry(0.2, 0), matInvisible)]
],
"XY": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0.15, 0.15, 0]
]
],
"YZ": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0, 0.15, 0.15],
[0, Math.PI / 2, 0]
]
],
"XZ": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0.15, 0, 0.15],
[-Math.PI / 2, 0, 0]
]
]
};
var helperTranslate = {
"START": [
[
new Mesh(new OctahedronGeometry(0.01, 2), matHelper),
null,
null,
null,
'helper'
]
],
"END": [
[
new Mesh(new OctahedronGeometry(0.01, 2), matHelper),
null,
null,
null,
'helper'
]
],
"DELTA": [
[
new Line(TranslateHelperGeometry(), matHelper),
null,
null,
null,
'helper'
]
],
"X": [
[
new Line(lineGeometry, matHelper.clone()),
[-1e3, 0, 0],
null,
[1e6, 1, 1],
'helper'
]
],
"Y": [
[
new Line(lineGeometry, matHelper.clone()),
[0, -1e3, 0],
[0, 0, Math.PI / 2],
[1e6, 1, 1],
'helper'
]
],
"Z": [
[
new Line(lineGeometry, matHelper.clone()),
[0, 0, -1e3],
[0, -Math.PI / 2, 0],
[1e6, 1, 1],
'helper'
]
]
};
var gizmoRotate = {
"XYZE": [
[
new Mesh(CircleGeometry(0.5, 1), matGray),
null,
[0, Math.PI / 2, 0]
]
],
"X": [
[new Mesh(CircleGeometry(0.5, 0.5), matRed)]
],
"Y": [
[
new Mesh(CircleGeometry(0.5, 0.5), matGreen),
null,
[0, 0, -Math.PI / 2]
]
],
"Z": [
[
new Mesh(CircleGeometry(0.5, 0.5), matBlue),
null,
[0, Math.PI / 2, 0]
]
],
"E": [
[
new Mesh(CircleGeometry(0.75, 1), matYellowTransparent),
null,
[0, Math.PI / 2, 0]
]
]
};
var helperRotate = {
"AXIS": [
[
new Line(lineGeometry, matHelper.clone()),
[-1e3, 0, 0],
null,
[1e6, 1, 1],
'helper'
]
]
};
var pickerRotate = {
"XYZE": [
[new Mesh(new SphereGeometry(0.25, 10, 8), matInvisible)]
],
"X": [
[
new Mesh(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible),
[0, 0, 0],
[0, -Math.PI / 2, -Math.PI / 2]
],
],
"Y": [
[
new Mesh(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible),
[0, 0, 0],
[Math.PI / 2, 0, 0]
],
],
"Z": [
[
new Mesh(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible),
[0, 0, 0],
[0, 0, -Math.PI / 2]
],
],
"E": [
[new Mesh(new TorusGeometry(0.75, 0.1, 2, 24), matInvisible)]
]
};
var gizmoScale = {
"X": [
[
new Mesh(scaleHandleGeometry, matRed),
[0.5, 0, 0],
[0, 0, -Math.PI / 2]
],
[
new Mesh(lineGeometry2, matRed),
[0, 0, 0],
[0, 0, -Math.PI / 2]
],
[
new Mesh(scaleHandleGeometry, matRed),
[-0.5, 0, 0],
[0, 0, Math.PI / 2]
],
],
"Y": [
[
new Mesh(scaleHandleGeometry, matGreen),
[0, 0.5, 0]
],
[new Mesh(lineGeometry2, matGreen)],
[
new Mesh(scaleHandleGeometry, matGreen),
[0, -0.5, 0],
[0, 0, Math.PI]
],
],
"Z": [
[
new Mesh(scaleHandleGeometry, matBlue),
[0, 0, 0.5],
[Math.PI / 2, 0, 0]
],
[
new Mesh(lineGeometry2, matBlue),
[0, 0, 0],
[Math.PI / 2, 0, 0]
],
[
new Mesh(scaleHandleGeometry, matBlue),
[0, 0, -0.5],
[-Math.PI / 2, 0, 0]
]
],
"XY": [
[
new Mesh(new BoxGeometry(0.15, 0.15, 0.01), matBlueTransparent),
[0.15, 0.15, 0]
]
],
"YZ": [
[
new Mesh(new BoxGeometry(0.15, 0.15, 0.01), matRedTransparent),
[0, 0.15, 0.15],
[0, Math.PI / 2, 0]
]
],
"XZ": [
[
new Mesh(new BoxGeometry(0.15, 0.15, 0.01), matGreenTransparent),
[0.15, 0, 0.15],
[-Math.PI / 2, 0, 0]
]
],
"XYZ": [
[new Mesh(new BoxGeometry(0.1, 0.1, 0.1), matWhiteTransparent.clone())],
]
};
var pickerScale = {
"X": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0.3, 0, 0],
[0, 0, -Math.PI / 2]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[-0.3, 0, 0],
[0, 0, Math.PI / 2]
]
],
"Y": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0.3, 0]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, -0.3, 0],
[0, 0, Math.PI]
]
],
"Z": [
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0, 0.3],
[Math.PI / 2, 0, 0]
],
[
new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),
[0, 0, -0.3],
[-Math.PI / 2, 0, 0]
]
],
"XY": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0.15, 0.15, 0]
],
],
"YZ": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0, 0.15, 0.15],
[0, Math.PI / 2, 0]
],
],
"XZ": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.01), matInvisible),
[0.15, 0, 0.15],
[-Math.PI / 2, 0, 0]
],
],
"XYZ": [
[
new Mesh(new BoxGeometry(0.2, 0.2, 0.2), matInvisible),
[0, 0, 0]
],
]
};
var helperScale = {
"X": [
[
new Line(lineGeometry, matHelper.clone()),
[-1e3, 0, 0],
null,
[1e6, 1, 1],
'helper'
]
],
"Y": [
[
new Line(lineGeometry, matHelper.clone()),
[0, -1e3, 0],
[0, 0, Math.PI / 2],
[1e6, 1, 1],
'helper'
]
],
"Z": [
[
new Line(lineGeometry, matHelper.clone()),
[0, 0, -1e3],
[0, -Math.PI / 2, 0],
[1e6, 1, 1],
'helper'
]
]
};
// Creates an Object3D with gizmos described in custom hierarchy definition.
var setupGizmo = (gizmoMap) {
var gizmo = new Object3D();
for (var name in gizmoMap.keys) {
var _len = gizmoMap[name].length;
for (var i = (_len - 1); i >= 0; i--) {
var _gi = gizmoMap[name][i];
dynamic object = null;
if (_gi.length > 0) {
object = _gi[0].clone();
}
List<num>? position;
if (_gi.length > 1) {
position = _gi[1];
}
List<num>? rotation;
if (_gi.length > 2) {
rotation = _gi[2];
}
List<num>? scale;
if (_gi.length > 3) {
scale = _gi[3];
}
dynamic tag = null;
if (_gi.length > 4) {
tag = _gi[4];
}
// name and tag properties are essential for picking and updating logic.
object.name = name;
object.tag = tag;
if (position != null) {
object.position.set(position[0].toDouble(), position[1].toDouble(), position[2].toDouble());
}
if (rotation != null) {
object.rotation.set(rotation[0].toDouble(), rotation[1].toDouble(), rotation[2].toDouble());
}
if (scale != null) {
object.scale.set(scale[0].toDouble(), scale[1].toDouble(), scale[2].toDouble());
}
object.updateMatrix();
var tempGeometry = object.geometry.clone();
tempGeometry.applyMatrix4(object.matrix);
object.geometry = tempGeometry;
object.renderOrder = Math.Infinity;
object.position.set(0.0, 0.0, 0.0);
object.rotation.set(0.0, 0.0, 0.0);
object.scale.set(1.0, 1.0, 1.0);
gizmo.add(object);
}
}
return gizmo;
};
// Gizmo creation
this.gizmo['translate'] = setupGizmo(gizmoTranslate);
this.gizmo['rotate'] = setupGizmo(gizmoRotate);
this.gizmo['scale'] = setupGizmo(gizmoScale);
this.picker['translate'] = setupGizmo(pickerTranslate);
this.picker['rotate'] = setupGizmo(pickerRotate);
this.picker['scale'] = setupGizmo(pickerScale);
this.helper['translate'] = setupGizmo(helperTranslate);
this.helper['rotate'] = setupGizmo(helperRotate);
this.helper['scale'] = setupGizmo(helperScale);
this.add(this.gizmo['translate']);
this.add(this.gizmo['rotate']);
this.add(this.gizmo['scale']);
this.add(this.picker['translate']);
this.add(this.picker['rotate']);
this.add(this.picker['scale']);
this.add(this.helper['translate']);
this.add(this.helper['rotate']);
this.add(this.helper['scale']);
// Pickers should be hidden always
this.picker['translate'].visible = false;
this.picker['rotate'].visible = false;
this.picker['scale'].visible = false;
}