Skip to content

Commit

Permalink
Gizmo features (#7050)
Browse files Browse the repository at this point in the history
* WIP: plane flip for translate gizmo

* Fixed plane flipping for any rotation and added to scale and translate

* Added update epsilon for plane flip

* changed update transform to just update position

* Add setting to enable flipping planes

* Added gizmo glancing angle hide

* Removed trailing spaces

* changed updates to prerender

* Added lower scale bound

* removed vector clones and resused tmp vectors

* Renamed scale lower bound
  • Loading branch information
kpal81xd committed Oct 21, 2024
1 parent 36c4826 commit c2993f3
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/extras/gizmo/gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,12 +456,12 @@ class Gizmo extends EventHandler {
_getSelection(x, y) {
const start = this._camera.entity.getPosition();
const end = this._camera.screenToWorld(x, y, this._camera.farClip - this._camera.nearClip);
const dir = end.clone().sub(start).normalize();
const dir = tmpV1.copy(end).sub(start).normalize();

const selection = [];
for (let i = 0; i < this.intersectShapes.length; i++) {
const shape = this.intersectShapes[i];
if (shape.disabled) {
if (shape.disabled || !shape.entity.enabled) {
continue;
}

Expand Down
46 changes: 45 additions & 1 deletion src/extras/gizmo/scale-gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const tmpV1 = new Vec3();
const tmpV2 = new Vec3();
const tmpQ1 = new Quat();

// constants
const GLANCE_EPSILON = 0.98;

/**
* Scaling gizmo.
*
Expand Down Expand Up @@ -105,6 +108,20 @@ class ScaleGizmo extends TransformGizmo {
*/
snapIncrement = 1;

/**
* Flips the planes to face the camera.
*
* @type {boolean}
*/
flipPlanes = true;

/**
* The lower bound for scaling.
*
* @type {Vec3}
*/
lowerBoundScale = new Vec3(-Infinity, -Infinity, -Infinity);

/**
* Creates a new ScaleGizmo object.
*
Expand Down Expand Up @@ -135,6 +152,10 @@ class ScaleGizmo extends TransformGizmo {
this.on(TransformGizmo.EVENT_NODESDETACH, () => {
this._nodeScales.clear();
});

this._app.on('prerender', () => {
this._planesLookAtCamera();
});
}

set coordSpace(value) {
Expand Down Expand Up @@ -347,6 +368,29 @@ class ScaleGizmo extends TransformGizmo {
this._shapes.xy[prop] = value;
}

/**
* @private
*/
_planesLookAtCamera() {
tmpV1.cross(this._camera.entity.forward, this.root.right);
this._shapes.yz.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.yz.flipped = tmpV2.set(0, +(tmpV1.dot(this.root.forward) > 0), +(tmpV1.dot(this.root.up) > 0));
}

tmpV1.cross(this._camera.entity.forward, this.root.forward);
this._shapes.xy.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.xy.flipped = tmpV2.set(+(tmpV1.dot(this.root.up) > 0), +(tmpV1.dot(this.root.right) < 0), 0);
}

tmpV1.cross(this._camera.entity.forward, this.root.up);
this._shapes.xz.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.xz.flipped = tmpV2.set(+(tmpV1.dot(this.root.forward) < 0), 0, +(tmpV1.dot(this.root.right) < 0));
}
}

/**
* @private
*/
Expand All @@ -368,7 +412,7 @@ class ScaleGizmo extends TransformGizmo {
if (!scale) {
continue;
}
node.setLocalScale(scale.clone().mul(pointDelta));
node.setLocalScale(tmpV1.copy(scale).mul(pointDelta).max(this.lowerBoundScale));
}
}

Expand Down
50 changes: 35 additions & 15 deletions src/extras/gizmo/shape/plane-shape.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { PlaneGeometry } from '../../../scene/geometry/plane-geometry.js';
import { TriData } from '../tri-data.js';
import { Shape } from './shape.js';

const UPDATE_EPSILON = 1e-6;

class PlaneShape extends Shape {
_cull = CULLFACE_NONE;

_size = 0.2;

_gap = 0.1;

_flipped = new Vec3();

constructor(device, options = {}) {
super(device, options);

Expand All @@ -21,21 +25,6 @@ class PlaneShape extends Shape {
this._createPlane();
}

_getPosition() {
const offset = this._size / 2 + this._gap;
const position = new Vec3(offset, offset, offset);
position[this.axis] = 0;
return position;
}

_createPlane() {
this._createRoot('plane');
this._updateTransform();

// plane
this._addRenderMesh(this.entity, 'plane', this._shading);
}

set size(value) {
this._size = value ?? 1;
this._updateTransform();
Expand All @@ -54,6 +43,37 @@ class PlaneShape extends Shape {
return this._gap;
}

set flipped(value) {
if (this._flipped.distance(value) < UPDATE_EPSILON) {
return;
}
this._flipped.copy(value);
this.entity.setLocalPosition(this._getPosition());
}

get flipped() {
return this._flipped;
}

_getPosition() {
const offset = this._size / 2 + this._gap;
const position = new Vec3(
this._flipped.x ? -offset : offset,
this._flipped.y ? -offset : offset,
this._flipped.z ? -offset : offset
);
position[this.axis] = 0;
return position;
}

_createPlane() {
this._createRoot('plane');
this._updateTransform();

// plane
this._addRenderMesh(this.entity, 'plane', this._shading);
}

_updateTransform() {
// intersect/render
this.entity.setLocalPosition(this._getPosition());
Expand Down
53 changes: 47 additions & 6 deletions src/extras/gizmo/translate-gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const tmpV1 = new Vec3();
const tmpV2 = new Vec3();
const tmpQ1 = new Quat();

// constants
const GLANCE_EPSILON = 0.98;

/**
* Translation gizmo.
*
Expand Down Expand Up @@ -109,6 +112,13 @@ class TranslateGizmo extends TransformGizmo {
*/
snapIncrement = 1;

/**
* Flips the planes to face the camera.
*
* @type {boolean}
*/
flipPlanes = true;

/**
* Creates a new TranslateGizmo object.
*
Expand Down Expand Up @@ -139,6 +149,10 @@ class TranslateGizmo extends TransformGizmo {
this._nodeLocalPositions.clear();
this._nodePositions.clear();
});

this._app.on('prerender', () => {
this._planesLookAtCamera();
});
}

/**
Expand Down Expand Up @@ -343,6 +357,29 @@ class TranslateGizmo extends TransformGizmo {
this._shapes.xy[prop] = value;
}

/**
* @private
*/
_planesLookAtCamera() {
tmpV1.cross(this._camera.entity.forward, this.root.right);
this._shapes.yz.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.yz.flipped = tmpV2.set(0, +(tmpV1.dot(this.root.forward) > 0), +(tmpV1.dot(this.root.up) > 0));
}

tmpV1.cross(this._camera.entity.forward, this.root.forward);
this._shapes.xy.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.xy.flipped = tmpV2.set(+(tmpV1.dot(this.root.up) > 0), +(tmpV1.dot(this.root.right) < 0), 0);
}

tmpV1.cross(this._camera.entity.forward, this.root.up);
this._shapes.xz.entity.enabled = tmpV1.length() < GLANCE_EPSILON;
if (this.flipPlanes) {
this._shapes.xz.flipped = tmpV2.set(+(tmpV1.dot(this.root.forward) < 0), 0, +(tmpV1.dot(this.root.right) < 0));
}
}

/**
* @private
*/
Expand All @@ -361,21 +398,25 @@ class TranslateGizmo extends TransformGizmo {
_setNodePositions(pointDelta) {
for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i];
const pos = this._nodePositions.get(node);
if (!pos) {
continue;
}
if (this._coordSpace === GIZMOSPACE_LOCAL) {
const pos = this._nodeLocalPositions.get(node);
if (!pos) {
continue;
}
tmpV1.copy(pointDelta);
node.parent?.getWorldTransform().getScale(tmpV2);
tmpV2.x = 1 / tmpV2.x;
tmpV2.y = 1 / tmpV2.y;
tmpV2.z = 1 / tmpV2.z;
tmpQ1.copy(node.getLocalRotation()).transformVector(tmpV1, tmpV1);
tmpV1.mul(tmpV2);
node.setLocalPosition(pos.clone().add(tmpV1));
node.setLocalPosition(tmpV1.add(pos));
} else {
node.setPosition(pos.clone().add(pointDelta));
const pos = this._nodePositions.get(node);
if (!pos) {
continue;
}
node.setPosition(tmpV1.copy(pointDelta).add(pos));
}
}

Expand Down

0 comments on commit c2993f3

Please sign in to comment.