Skip to content

Commit

Permalink
GraphNode setPositionAndRotation (#6625)
Browse files Browse the repository at this point in the history
* added new method on graph node for setting position and rotation together

* set transform on entity directly instead of using parent

* added back the same position and rotation logic and test for setPositionAndRotation

* removed extra call to get ptm

* removed mat3 and used inv parent matrix directly

* revereted example changes

* Updated description of setPositionAndRotation
  • Loading branch information
kpal81xd authored Jun 4, 2024
1 parent 9b11cd2 commit 5c44889
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/scene/graph-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,32 @@ class GraphNode extends EventHandler {
this._dirtifyLocal();
}

/**
* Sets the world-space position and rotation of the specified graph node. This is faster than
* setting the position and rotation independently.
*
* @param {Vec3} position - The world-space position to set.
* @param {Quat} rotation - The world-space rotation to set.
* @example
* const position = new pc.Vec3(0, 10, 0);
* const rotation = new pc.Quat().setFromEulerAngles(0, 90, 0);
* this.entity.setPositionAndRotation(position, rotation);
*/
setPositionAndRotation(position, rotation) {
if (this._parent === null) {
this.localPosition.copy(position);
this.localRotation.copy(rotation);
} else {
const parentWtm = this._parent.getWorldTransform();
invParentWtm.copy(parentWtm).invert();
invParentWtm.transformPoint(position, this.localPosition);
this.localRotation.setFromMat4(invParentWtm).mul(rotation);
}

if (!this._dirtyLocal)
this._dirtifyLocal();
}

/**
* Sets the world-space rotation of the specified graph node using euler angles. Eulers are
* interpreted in XYZ order. Eulers must be specified in degrees. This function has two valid
Expand Down
44 changes: 44 additions & 0 deletions test/scene/graph-node.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -851,4 +851,48 @@ describe('GraphNode', function () {

});

describe('#setPositionAndRotation()', function () {
it('setPositionAndRotation is the same as setPosition and setRotation', function () {
const root = new GraphNode('root');
const child = new GraphNode('child');
root.addChild(child);
root.setPosition(10, 20, 30);

root.setLocalScale(0.5, 0.5, 0.5);

const pos = new Vec3(1, 2, 3);
const rot = new Quat().setFromEulerAngles(10, 20, 30);
child.setPosition(pos);
child.setRotation(rot);

const pos1 = child.getPosition().clone();
const rot1 = child.getRotation().clone();
const localPos1 = child.getLocalPosition().clone();
const localRot1 = child.getLocalRotation().clone();

child.setPositionAndRotation(pos, rot);

const pos2 = child.getPosition();
expect(pos2.x).to.be.closeTo(pos1.x, 0.00001);
expect(pos2.y).to.be.closeTo(pos1.y, 0.00001);
expect(pos2.z).to.be.closeTo(pos1.z, 0.00001);

const rot2 = child.getRotation();
expect(rot2.x).to.be.closeTo(rot1.x, 0.00001);
expect(rot2.y).to.be.closeTo(rot1.y, 0.00001);
expect(rot2.z).to.be.closeTo(rot1.z, 0.00001);
expect(rot2.w).to.be.closeTo(rot1.w, 0.00001);

const localPos2 = child.getLocalPosition();
expect(localPos2.x).to.be.closeTo(localPos1.x, 0.00001);
expect(localPos2.y).to.be.closeTo(localPos1.y, 0.00001);
expect(localPos2.z).to.be.closeTo(localPos1.z, 0.00001);

const localRot2 = child.getLocalRotation();
expect(localRot2.x).to.be.closeTo(localRot1.x, 0.00001);
expect(localRot2.y).to.be.closeTo(localRot1.y, 0.00001);
expect(localRot2.z).to.be.closeTo(localRot1.z, 0.00001);
expect(localRot2.w).to.be.closeTo(localRot1.w, 0.00001);
});
});
});

0 comments on commit 5c44889

Please sign in to comment.