Skip to content

Commit 3da8ccc

Browse files
committed
Emitter: fix Axis alignment mode flipping side, due to euler angles not being normalized. Introduce new align mode ScreenZ useful for screen-aligned polys rotating around Z axis.
1 parent 754645e commit 3da8ccc

File tree

1 file changed

+39
-16
lines changed

1 file changed

+39
-16
lines changed

hrt/prefab/fx/Emitter.hx

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ enum AlignLockAxis {
1919
X;
2020
Y;
2121
Z;
22+
ScreenZ; // Screen-facing flat polygons rotating around Z
2223
}
2324

2425
enum EmitShape {
@@ -825,11 +826,9 @@ class EmitterObject extends h3d.scene.Object {
825826
return;
826827

827828
if( parent != null ) {
828-
invTransform.load(parent.getInvPos());
829829

830-
if(alignMode == Screen || alignMode == Axis) {
831-
var cam = getScene().camera;
832-
tmpMat.load(cam.mcam);
830+
if(alignMode == Screen) {
831+
tmpMat.load(getScene().camera.mcam);
833832
tmpMat.invert();
834833

835834
if(simulationSpace == Local) { // Compensate parent rotation
@@ -840,19 +839,43 @@ class EmitterObject extends h3d.scene.Object {
840839
tmpMat.multiply(tmpMat, tmpMat2);
841840
}
842841

843-
if(alignMode == Axis) {
844-
var a = getEulerAngles(tmpMat);
845-
switch alignLockAxis {
846-
case X: screenQuat.initRotation(a.x, 0, 0);
847-
case Y: screenQuat.initRotation(0, a.y, 0);
848-
case Z: screenQuat.initRotation(0, 0, a.z);
849-
}
842+
screenQuat.initRotateMatrix(tmpMat);
843+
tmpQuat.initRotateAxis(1,0,0,Math.PI); // Flip Y axis so Y is pointing down
844+
screenQuat.multiply(screenQuat, tmpQuat);
845+
}
846+
else if(alignMode == Axis) {
847+
var lockAxis = new h3d.Vector();
848+
var frontAxis = new h3d.Vector(1, 0, 0);
849+
switch alignLockAxis {
850+
case X: lockAxis.set(1, 0, 0);
851+
case Y: lockAxis.set(0, 1, 0);
852+
case Z: lockAxis.set(0, 0, 1);
853+
case ScreenZ:
854+
lockAxis.set(0, 0, 1);
855+
frontAxis.set(0, 1, 0);
850856
}
851-
else
852-
screenQuat.initRotateMatrix(tmpMat);
853857

854-
if(alignMode == Screen) {
855-
tmpQuat.initRotateAxis(1,0,0,Math.PI); // Flip Y axis so Y is pointing down
858+
var lookAtPos = tmpVec;
859+
lookAtPos.load(getScene().camera.pos);
860+
invTransform.load(parent.getInvPos());
861+
lookAtPos.transform(invTransform);
862+
var deltaVec = new h3d.Vector(lookAtPos.x - x, lookAtPos.y - y, lookAtPos.z - z);
863+
864+
var invParentQ = tmpQuat;
865+
invParentQ.initRotateMatrix(invTransform);
866+
867+
var targetOnPlane = h3d.col.Plane.fromNormalPoint(lockAxis.toPoint(), new h3d.col.Point()).project(deltaVec.toPoint()).toVector();
868+
targetOnPlane.normalize();
869+
var angle = hxd.Math.acos(frontAxis.dot(targetOnPlane));
870+
871+
var cross = frontAxis.cross(deltaVec);
872+
if(lockAxis.dot(cross) < 0)
873+
angle = -angle;
874+
875+
screenQuat.initRotateAxis(lockAxis.x, lockAxis.y, lockAxis.z, angle);
876+
screenQuat.normalize();
877+
if(alignLockAxis == ScreenZ) {
878+
tmpQuat.initRotateAxis(1,0,0,-Math.PI/2);
856879
screenQuat.multiply(screenQuat, tmpQuat);
857880
}
858881
}
@@ -1090,7 +1113,7 @@ class Emitter extends Object3D {
10901113
{ name: "emitSurface", t: PBool, def: false, disp: "Surface", groupName : "Emit Shape" },
10911114
// ALIGNMENT
10921115
{ name: "alignMode", t: PEnum(AlignMode), def: AlignMode.None, disp: "Mode", groupName : "Alignment" },
1093-
{ name: "alignLockAxis", t: PEnum(AlignLockAxis), def: AlignLockAxis.Z, disp: "Lock Axis", groupName : "Alignment" },
1116+
{ name: "alignLockAxis", t: PEnum(AlignLockAxis), def: AlignLockAxis.ScreenZ, disp: "Lock Axis", groupName : "Alignment" },
10941117
// COLOR
10951118
{ name: "useRandomColor", t: PBool, def: false, disp: "Random Color", groupName : "Color" },
10961119
{ name: "randomColor1", t: PVec(4), disp: "Color 1", def : [0,0,0,1], groupName : "Color" },

0 commit comments

Comments
 (0)