From a3ddf62e0097d481e8ac3a0cd6fe65e41040ff4a Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 17 Jan 2005 06:04:45 +0000 Subject: [PATCH] add LerpQuatInterval and related --- direct/src/extensions/NodePath-extensions.py | 20 ++ direct/src/interval/LerpInterval.py | 252 +++++++++++++++++- direct/src/interval/cLerpNodePathInterval.I | 94 ++++++- direct/src/interval/cLerpNodePathInterval.cxx | 89 ++++++- direct/src/interval/cLerpNodePathInterval.h | 19 +- 5 files changed, 442 insertions(+), 32 deletions(-) diff --git a/direct/src/extensions/NodePath-extensions.py b/direct/src/extensions/NodePath-extensions.py index 09a698e584..a661753d89 100644 --- a/direct/src/extensions/NodePath-extensions.py +++ b/direct/src/extensions/NodePath-extensions.py @@ -955,6 +955,10 @@ def hprInterval(self, *args, **kw): from direct.interval import LerpInterval return LerpInterval.LerpHprInterval(self, *args, **kw) + + def quatInterval(self, *args, **kw): + from direct.interval import LerpInterval + return LerpInterval.LerpQuatInterval(self, *args, **kw) def scaleInterval(self, *args, **kw): from direct.interval import LerpInterval @@ -968,18 +972,34 @@ from direct.interval import LerpInterval return LerpInterval.LerpPosHprInterval(self, *args, **kw) + def posQuatInterval(self, *args, **kw): + from direct.interval import LerpInterval + return LerpInterval.LerpPosQuatInterval(self, *args, **kw) + def hprScaleInterval(self, *args, **kw): from direct.interval import LerpInterval return LerpInterval.LerpHprScaleInterval(self, *args, **kw) + def quatScaleInterval(self, *args, **kw): + from direct.interval import LerpInterval + return LerpInterval.LerpQuatScaleInterval(self, *args, **kw) + def posHprScaleInterval(self, *args, **kw): from direct.interval import LerpInterval return LerpInterval.LerpPosHprScaleInterval(self, *args, **kw) + def posQuatScaleInterval(self, *args, **kw): + from direct.interval import LerpInterval + return LerpInterval.LerpPosQuatScaleInterval(self, *args, **kw) + def posHprScaleShearInterval(self, *args, **kw): from direct.interval import LerpInterval return LerpInterval.LerpPosHprScaleShearInterval(self, *args, **kw) + def posQuatScaleShearInterval(self, *args, **kw): + from direct.interval import LerpInterval + return LerpInterval.LerpPosQuatScaleShearInterval(self, *args, **kw) + def colorInterval(self, *args, **kw): from direct.interval import LerpInterval return LerpInterval.LerpColorInterval(self, *args, **kw) diff --git a/direct/src/interval/LerpInterval.py b/direct/src/interval/LerpInterval.py index 7de86465f4..4d3af4a112 100644 --- a/direct/src/interval/LerpInterval.py +++ b/direct/src/interval/LerpInterval.py @@ -108,22 +108,26 @@ class LerpPosInterval(LerpNodePathInterval): class LerpHprInterval(LerpNodePathInterval): - def __init__(self, nodePath, duration, hpr, startHpr = None, + def __init__(self, nodePath, duration, hpr, + startHpr = None, startQuat = None, other = None, blendType = 'noBlend', bakeInStart = 1, fluid = 0, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, bakeInStart, fluid, nodePath, other) # Check for functors in the input parameters. - self.paramSetup = self.anyCallable(hpr, startHpr) + self.paramSetup = self.anyCallable(hpr, startHpr, startQuat) if self.paramSetup: self.endHpr = hpr self.startHpr = startHpr + self.startQuat = startQuat self.inPython = 1 else: self.setEndHpr(hpr) if startHpr != None: self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) def privDoEvent(self, t, event): # This function is only used if Python functors were passed in @@ -131,6 +135,38 @@ class LerpHprInterval(LerpNodePathInterval): if self.paramSetup and event == CInterval.ETInitialize: self.setupParam(self.setEndHpr, self.endHpr) self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) + LerpNodePathInterval.privDoEvent(self, t, event) + +class LerpQuatInterval(LerpNodePathInterval): + def __init__(self, nodePath, duration, quat, + startHpr = None, startQuat = None, + other = None, blendType = 'noBlend', + bakeInStart = 1, fluid = 0, name = None): + LerpNodePathInterval.__init__(self, name, duration, blendType, + bakeInStart, fluid, nodePath, other) + + # Check for functors in the input parameters. + self.paramSetup = self.anyCallable(quat, startHpr, startQuat) + if self.paramSetup: + self.endQuat = quat + self.startHpr = startHpr + self.startQuat = startQuat + self.inPython = 1 + else: + self.setEndQuat(quat) + if startHpr != None: + self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) + + def privDoEvent(self, t, event): + # This function is only used if Python functors were passed in + # for some of the input parameters. + if self.paramSetup and event == CInterval.ETInitialize: + self.setupParam(self.setEndQuat, self.endQuat) + self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) class LerpScaleInterval(LerpNodePathInterval): @@ -185,18 +221,19 @@ class LerpShearInterval(LerpNodePathInterval): class LerpPosHprInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, - startPos = None, startHpr = None, + startPos = None, startHpr = None, startQuat = None, other = None, blendType = 'noBlend', bakeInStart = 1, fluid = 0, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, bakeInStart, fluid, nodePath, other) # Check for functors in the input parameters. - self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr) + self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, startQuat) if self.paramSetup: self.endPos = pos self.startPos = startPos self.endHpr = hpr self.startHpr = startHpr + self.startQuat = startQuat self.inPython = 1 else: self.setEndPos(pos) @@ -205,6 +242,8 @@ class LerpPosHprInterval(LerpNodePathInterval): self.setEndHpr(hpr) if startHpr != None: self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) def privDoEvent(self, t, event): # This function is only used if Python functors were passed in @@ -214,21 +253,60 @@ class LerpPosHprInterval(LerpNodePathInterval): self.setupParam(self.setStartPos, self.startPos) self.setupParam(self.setEndHpr, self.endHpr) self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) + LerpNodePathInterval.privDoEvent(self, t, event) + +class LerpPosQuatInterval(LerpNodePathInterval): + def __init__(self, nodePath, duration, pos, quat, + startPos = None, startHpr = None, startQuat = None, + other = None, blendType = 'noBlend', + bakeInStart = 1, fluid = 0, name = None): + LerpNodePathInterval.__init__(self, name, duration, blendType, + bakeInStart, fluid, nodePath, other) + # Check for functors in the input parameters. + self.paramSetup = self.anyCallable(pos, startPos, quat, startHpr, startQuat) + if self.paramSetup: + self.endPos = pos + self.startPos = startPos + self.endQuat = quat + self.startHpr = startHpr + self.startQuat = startQuat + self.inPython = 1 + else: + self.setEndPos(pos) + if startPos != None: + self.setStartPos(startPos) + self.setEndQuat(quat) + if startHpr != None: + self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) + + def privDoEvent(self, t, event): + # This function is only used if Python functors were passed in + # for some of the input parameters. + if self.paramSetup and event == CInterval.ETInitialize: + self.setupParam(self.setEndPos, self.endPos) + self.setupParam(self.setStartPos, self.startPos) + self.setupParam(self.setEndQuat, self.endQuat) + self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) LerpNodePathInterval.privDoEvent(self, t, event) class LerpHprScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, hpr, scale, - startHpr = None, startScale = None, + startHpr = None, startQuat = None, startScale = None, other = None, blendType = 'noBlend', bakeInStart = 1, fluid = 0, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, bakeInStart, fluid, nodePath, other) # Check for functors in the input parameters. - self.paramSetup = self.anyCallable(hpr, startHpr, scale, startScale) + self.paramSetup = self.anyCallable(hpr, startHpr, startQuat, scale, startScale) if self.paramSetup: self.endHpr = hpr self.startHpr = startHpr + self.startQuat = startQuat self.endScale = scale self.startScale = startScale self.inPython = 1 @@ -236,6 +314,8 @@ class LerpHprScaleInterval(LerpNodePathInterval): self.setEndHpr(hpr) if startHpr != None: self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) self.setEndScale(scale) if startScale != None: self.setStartScale(startScale) @@ -246,24 +326,66 @@ class LerpHprScaleInterval(LerpNodePathInterval): if self.paramSetup and event == CInterval.ETInitialize: self.setupParam(self.setEndHpr, self.endHpr) self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) + self.setupParam(self.setEndScale, self.endScale) + self.setupParam(self.setStartScale, self.startScale) + LerpNodePathInterval.privDoEvent(self, t, event) + +class LerpQuatScaleInterval(LerpNodePathInterval): + def __init__(self, nodePath, duration, quat, scale, + startHpr = None, startQuat = None, startScale = None, + other = None, blendType = 'noBlend', + bakeInStart = 1, fluid = 0, name = None): + LerpNodePathInterval.__init__(self, name, duration, blendType, + bakeInStart, fluid, nodePath, other) + + # Check for functors in the input parameters. + self.paramSetup = self.anyCallable(quat, startHpr, startQuat, scale, startScale) + if self.paramSetup: + self.endQuat = quat + self.startHpr = startHpr + self.startQuat = startQuat + self.endScale = scale + self.startScale = startScale + self.inPython = 1 + else: + self.setEndQuat(quat) + if startHpr != None: + self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) + self.setEndScale(scale) + if startScale != None: + self.setStartScale(startScale) + + def privDoEvent(self, t, event): + # This function is only used if Python functors were passed in + # for some of the input parameters. + if self.paramSetup and event == CInterval.ETInitialize: + self.setupParam(self.setEndQuat, self.endQuat) + self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setEndScale, self.endScale) self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) class LerpPosHprScaleInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, scale, - startPos = None, startHpr = None, startScale = None, + startPos = None, startHpr = None, startQuat = None, + startScale = None, other = None, blendType = 'noBlend', bakeInStart = 1, fluid = 0, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, bakeInStart, fluid, nodePath, other) # Check for functors in the input parameters. - self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale) + self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, + startQuat, scale, startScale) if self.paramSetup: self.endPos = pos self.startPos = startPos self.endHpr = hpr self.startHpr = startHpr + self.startQuat = startQuat self.endScale = scale self.startScale = startScale self.inPython = 1 @@ -274,6 +396,8 @@ class LerpPosHprScaleInterval(LerpNodePathInterval): self.setEndHpr(hpr) if startHpr != None: self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) self.setEndScale(scale) if startScale != None: self.setStartScale(startScale) @@ -286,24 +410,75 @@ class LerpPosHprScaleInterval(LerpNodePathInterval): self.setupParam(self.setStartPos, self.startPos) self.setupParam(self.setEndHpr, self.endHpr) self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) + self.setupParam(self.setEndScale, self.endScale) + self.setupParam(self.setStartScale, self.startScale) + LerpNodePathInterval.privDoEvent(self, t, event) + +class LerpPosQuatScaleInterval(LerpNodePathInterval): + def __init__(self, nodePath, duration, pos, quat, scale, + startPos = None, startHpr = None, startQuat = None, + startScale = None, + other = None, blendType = 'noBlend', + bakeInStart = 1, fluid = 0, name = None): + LerpNodePathInterval.__init__(self, name, duration, blendType, + bakeInStart, fluid, nodePath, other) + # Check for functors in the input parameters. + self.paramSetup = self.anyCallable(pos, startPos, quat, startHpr, + startQuat, scale, startScale) + if self.paramSetup: + self.endPos = pos + self.startPos = startPos + self.endQuat = quat + self.startHpr = startHpr + self.startQuat = startQuat + self.endScale = scale + self.startScale = startScale + self.inPython = 1 + else: + self.setEndPos(pos) + if startPos != None: + self.setStartPos(startPos) + self.setEndQuat(quat) + if startHpr != None: + self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) + self.setEndScale(scale) + if startScale != None: + self.setStartScale(startScale) + + def privDoEvent(self, t, event): + # This function is only used if Python functors were passed in + # for some of the input parameters. + if self.paramSetup and event == CInterval.ETInitialize: + self.setupParam(self.setEndPos, self.endPos) + self.setupParam(self.setStartPos, self.startPos) + self.setupParam(self.setEndQuat, self.endQuat) + self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setEndScale, self.endScale) self.setupParam(self.setStartScale, self.startScale) LerpNodePathInterval.privDoEvent(self, t, event) class LerpPosHprScaleShearInterval(LerpNodePathInterval): def __init__(self, nodePath, duration, pos, hpr, scale, shear, - startPos = None, startHpr = None, startScale = None, startShear = None, + startPos = None, startHpr = None, startQuat = None, + startScale = None, startShear = None, other = None, blendType = 'noBlend', bakeInStart = 1, fluid = 0, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, bakeInStart, fluid, nodePath, other) # Check for functors in the input parameters. - self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale, shear, startShear) + self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, + startQuat, scale, startScale, + shear, startShear) if self.paramSetup: self.endPos = pos self.startPos = startPos self.endHpr = hpr self.startHpr = startHpr + self.startQuat = startQuat self.endScale = scale self.startScale = startScale self.endShear = shear @@ -316,6 +491,8 @@ class LerpPosHprScaleShearInterval(LerpNodePathInterval): self.setEndHpr(hpr) if startHpr != None: self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) self.setEndScale(scale) if startScale != None: self.setStartScale(startScale) @@ -331,6 +508,61 @@ class LerpPosHprScaleShearInterval(LerpNodePathInterval): self.setupParam(self.setStartPos, self.startPos) self.setupParam(self.setEndHpr, self.endHpr) self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) + self.setupParam(self.setEndScale, self.endScale) + self.setupParam(self.setStartScale, self.startScale) + self.setupParam(self.setEndShear, self.endShear) + self.setupParam(self.setStartShear, self.startShear) + LerpNodePathInterval.privDoEvent(self, t, event) + +class LerpPosQuatScaleShearInterval(LerpNodePathInterval): + def __init__(self, nodePath, duration, pos, quat, scale, shear, + startPos = None, startHpr = None, startQuat = None, + startScale = None, startShear = None, + other = None, blendType = 'noBlend', + bakeInStart = 1, fluid = 0, name = None): + LerpNodePathInterval.__init__(self, name, duration, blendType, + bakeInStart, fluid, nodePath, other) + # Check for functors in the input parameters. + self.paramSetup = self.anyCallable(pos, startPos, quat, startHpr, + startQuat, scale, startScale, + shear, startShear) + if self.paramSetup: + self.endPos = pos + self.startPos = startPos + self.endQuat = quat + self.startHpr = startHpr + self.startQuat = startQuat + self.endScale = scale + self.startScale = startScale + self.endShear = shear + self.startShear = startShear + self.inPython = 1 + else: + self.setEndPos(pos) + if startPos != None: + self.setStartPos(startPos) + self.setEndQuat(quat) + if startHpr != None: + self.setStartHpr(startHpr) + if startQuat != None: + self.setStartQuat(startQuat) + self.setEndScale(scale) + if startScale != None: + self.setStartScale(startScale) + self.setEndShear(shear) + if startShear != None: + self.setStartShear(startShear) + + def privDoEvent(self, t, event): + # This function is only used if Python functors were passed in + # for some of the input parameters. + if self.paramSetup and event == CInterval.ETInitialize: + self.setupParam(self.setEndPos, self.endPos) + self.setupParam(self.setStartPos, self.startPos) + self.setupParam(self.setEndQuat, self.endQuat) + self.setupParam(self.setStartHpr, self.startHpr) + self.setupParam(self.setStartQuat, self.startQuat) self.setupParam(self.setEndScale, self.endScale) self.setupParam(self.setStartScale, self.startScale) self.setupParam(self.setEndShear, self.endShear) diff --git a/direct/src/interval/cLerpNodePathInterval.I b/direct/src/interval/cLerpNodePathInterval.I index 190fa818bf..1ee4faf78a 100644 --- a/direct/src/interval/cLerpNodePathInterval.I +++ b/direct/src/interval/cLerpNodePathInterval.I @@ -74,10 +74,11 @@ set_end_pos(const LVecBase3f &pos) { // Function: CLerpNodePathInterval::set_start_hpr // Access: Published // Description: Indicates the initial rotation of the lerped node. -// This is meaningful only if set_end_hpr() is also -// called. This parameter is optional; if unspecified, -// the value will be taken from the node's actual -// rotation at the time the lerp is performed. +// This is meaningful only if either set_end_hpr() or +// set_end_quat() is also called. This parameter is +// optional; if unspecified, the value will be taken +// from the node's actual rotation at the time the lerp +// is performed. //////////////////////////////////////////////////////////////////// INLINE void CLerpNodePathInterval:: set_start_hpr(const LVecBase3f &hpr) { @@ -90,14 +91,91 @@ set_start_hpr(const LVecBase3f &hpr) { // Access: Published // Description: Indicates that the rotation of the node should be // lerped, and specifies the final rotation of the node. -// This should be called before priv_initialize(). If this -// is not called, the node's rotation will not be -// affected by the lerp. +// This should be called before priv_initialize(). +// +// This replaces a previous call to set_end_quat(). If +// neither set_end_hpr() nor set_end_quat() is called, +// the node's rotation will not be affected by the lerp. //////////////////////////////////////////////////////////////////// INLINE void CLerpNodePathInterval:: set_end_hpr(const LVecBase3f &hpr) { _end_hpr = hpr; - _flags |= F_end_hpr; + _flags = (_flags & ~F_end_quat) | F_end_hpr; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLerpNodePathInterval::set_end_hpr +// Access: Published +// Description: Indicates that the rotation of the node should be +// lerped, and specifies the final rotation of the node. +// This should be called before priv_initialize(). +// +// This special function is overloaded to accept a +// quaternion, even though the function name is +// set_end_hpr(). The quaternion will be implicitly +// converted to a HPR trio, and the lerp will be +// performed in HPR space, componentwise. +//////////////////////////////////////////////////////////////////// +INLINE void CLerpNodePathInterval:: +set_end_hpr(const LQuaternionf &quat) { + _end_hpr = quat.get_hpr(); + _flags = (_flags & ~F_end_quat) | F_end_hpr; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLerpNodePathInterval::set_start_quat +// Access: Published +// Description: Indicates the initial rotation of the lerped node. +// This is meaningful only if either set_end_quat() or +// set_end_hpr() is also called. This parameter is +// optional; if unspecified, the value will be taken +// from the node's actual rotation at the time the lerp +// is performed. +//////////////////////////////////////////////////////////////////// +INLINE void CLerpNodePathInterval:: +set_start_quat(const LQuaternionf &quat) { + _start_quat = quat; + _flags |= F_start_quat; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLerpNodePathInterval::set_end_quat +// Access: Published +// Description: Indicates that the rotation of the node should be +// lerped, and specifies the final rotation of the node. +// This should be called before priv_initialize(). +// +// This replaces a previous call to set_end_hpr(). If +// neither set_end_quat() nor set_end_hpr() is called, +// the node's rotation will not be affected by the lerp. +// +// This special function is overloaded to accept a HPR +// trio, even though the function name is +// set_end_quat(). The HPR will be implicitly converted +// to a quaternion, and the lerp will be performed in +// quaternion space, as a spherical lerp. +//////////////////////////////////////////////////////////////////// +INLINE void CLerpNodePathInterval:: +set_end_quat(const LVecBase3f &hpr) { + _end_quat.set_hpr(hpr); + _flags = (_flags & ~F_end_hpr) | F_end_quat; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLerpNodePathInterval::set_end_quat +// Access: Published +// Description: Indicates that the rotation of the node should be +// lerped, and specifies the final rotation of the node. +// This should be called before priv_initialize(). +// +// This replaces a previous call to set_end_hpr(). If +// neither set_end_quat() nor set_end_hpr() is called, +// the node's rotation will not be affected by the lerp. +//////////////////////////////////////////////////////////////////// +INLINE void CLerpNodePathInterval:: +set_end_quat(const LQuaternionf &quat) { + _end_quat = quat; + _flags = (_flags & ~F_end_hpr) | F_end_quat; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/interval/cLerpNodePathInterval.cxx b/direct/src/interval/cLerpNodePathInterval.cxx index 55a1e0694d..bc10817aba 100644 --- a/direct/src/interval/cLerpNodePathInterval.cxx +++ b/direct/src/interval/cLerpNodePathInterval.cxx @@ -128,7 +128,7 @@ priv_step(double t) { // Save this in case we want to restore it later. CPT(TransformState) prev_transform = _node.get_prev_transform(); - if ((_flags & (F_end_pos | F_end_hpr | F_end_scale | F_end_shear)) != 0) { + if ((_flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale | F_end_shear)) != 0) { // We have some transform lerp. CPT(TransformState) transform; @@ -143,6 +143,7 @@ priv_step(double t) { LPoint3f pos; LVecBase3f hpr; + LQuaternionf quat; LVecBase3f scale; LVecBase3f shear; @@ -165,6 +166,11 @@ priv_step(double t) { if ((_flags & F_start_hpr) != 0) { lerp_value(hpr, d, _start_hpr, _end_hpr); + } else if ((_flags & F_start_quat) != 0) { + _start_hpr = _start_quat.get_hpr(); + _flags |= F_start_hpr; + lerp_value(hpr, d, _start_hpr, _end_hpr); + } else if ((_flags & F_bake_in_start) != 0) { set_start_hpr(transform->get_hpr()); lerp_value(hpr, d, _start_hpr, _end_hpr); @@ -174,6 +180,25 @@ priv_step(double t) { lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr); } } + if ((_flags & F_end_quat) != 0) { + if ((_flags & F_start_quat) != 0) { + lerp_value(quat, d, _start_quat, _end_quat); + + } else if ((_flags & F_start_hpr) != 0) { + _start_quat.set_hpr(_start_hpr); + _flags |= F_start_quat; + lerp_value(quat, d, _start_quat, _end_quat); + + } else if ((_flags & F_bake_in_start) != 0) { + set_start_quat(transform->get_quat()); + lerp_value(quat, d, _start_quat, _end_quat); + + } else { + quat = transform->get_quat(); + lerp_value_from_prev(quat, d, _prev_d, quat, _end_quat); + } + quat.normalize(); + } if ((_flags & F_end_scale) != 0) { if ((_flags & F_start_scale) != 0) { lerp_value(scale, d, _start_scale, _end_scale); @@ -206,7 +231,8 @@ priv_step(double t) { // transform has hpr/scale components if they're not needed. And // in any case, we only want to apply the components that we // computed, above. - switch (_flags & (F_end_pos | F_end_hpr | F_end_scale)) { + unsigned int transform_flags = _flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale); + switch (transform_flags) { case 0: break; @@ -226,6 +252,14 @@ priv_step(double t) { } break; + case F_end_quat: + if (_other.is_empty()) { + _node.set_quat(quat); + } else { + _node.set_quat(_other, quat); + } + break; + case F_end_scale: if (_other.is_empty()) { _node.set_scale(scale); @@ -242,6 +276,14 @@ priv_step(double t) { } break; + case F_end_quat | F_end_scale: + if (_other.is_empty()) { + _node.set_quat_scale(quat, scale); + } else { + _node.set_quat_scale(quat, scale); + } + break; + case F_end_pos | F_end_hpr: if (_other.is_empty()) { _node.set_pos_hpr(pos, hpr); @@ -250,6 +292,14 @@ priv_step(double t) { } break; + case F_end_pos | F_end_quat: + if (_other.is_empty()) { + _node.set_pos_quat(pos, quat); + } else { + _node.set_pos_quat(_other, pos, quat); + } + break; + case F_end_pos | F_end_scale: if (transform->quat_given()) { if (_other.is_empty()) { @@ -284,16 +334,33 @@ priv_step(double t) { } break; + case F_end_pos | F_end_quat | F_end_scale: + if ((_flags & F_end_shear) != 0) { + // Even better: we have all four components. + if (_other.is_empty()) { + _node.set_pos_quat_scale_shear(pos, quat, scale, shear); + } else { + _node.set_pos_quat_scale_shear(_other, pos, quat, scale, shear); + } + } else { + // We have only the primary three components. + if (_other.is_empty()) { + _node.set_pos_quat_scale(pos, quat, scale); + } else { + _node.set_pos_quat_scale(_other, pos, quat, scale); + } + } + break; + default: // Some unhandled combination. We should handle this. interval_cat.error() << "Internal error in CLerpNodePathInterval::priv_step().\n"; } - if ((_flags & F_end_shear) != 0) { // Also apply changes to shear. - if ((_flags & (F_end_pos | F_end_hpr | F_end_scale)) == - (F_end_pos | F_end_hpr | F_end_scale)) { + if (transform_flags == (F_end_pos | F_end_hpr | F_end_scale) || + transform_flags == (F_end_pos | F_end_quat | F_end_scale)) { // Actually, we already handled this case above. } else { @@ -384,9 +451,7 @@ priv_step(double t) { } else { _node.set_state(_other, state); } - } - - _prev_d = d; + } _prev_d = d; _curr_t = t; } @@ -451,6 +516,14 @@ output(ostream &out) const { out << " to " << _end_hpr; } + if ((_flags & F_end_quat) != 0) { + out << " quat"; + if ((_flags & F_start_quat) != 0) { + out << " from " << _start_quat; + } + out << " to " << _end_quat; + } + if ((_flags & F_end_scale) != 0) { out << " scale"; if ((_flags & F_start_scale) != 0) { diff --git a/direct/src/interval/cLerpNodePathInterval.h b/direct/src/interval/cLerpNodePathInterval.h index e2652f46c2..b942e51d72 100644 --- a/direct/src/interval/cLerpNodePathInterval.h +++ b/direct/src/interval/cLerpNodePathInterval.h @@ -42,6 +42,10 @@ PUBLISHED: INLINE void set_end_pos(const LVecBase3f &pos); INLINE void set_start_hpr(const LVecBase3f &hpr); INLINE void set_end_hpr(const LVecBase3f &hpr); + INLINE void set_end_hpr(const LQuaternionf &quat); + INLINE void set_start_quat(const LQuaternionf &quat); + INLINE void set_end_quat(const LVecBase3f &hpr); + INLINE void set_end_quat(const LQuaternionf &quat); INLINE void set_start_scale(const LVecBase3f &scale); INLINE void set_start_scale(float scale); INLINE void set_end_scale(const LVecBase3f &scale); @@ -68,13 +72,15 @@ private: enum Flags { F_end_pos = 0x0001, F_end_hpr = 0x0002, - F_end_scale = 0x0004, - F_end_color = 0x0008, - F_end_color_scale = 0x0010, - F_end_shear = 0x0020, + F_end_quat = 0x0004, + F_end_scale = 0x0008, + F_end_color = 0x0010, + F_end_color_scale = 0x0020, + F_end_shear = 0x0040, - F_start_pos = 0x0100, - F_start_hpr = 0x0200, + F_start_pos = 0x0080, + F_start_hpr = 0x0100, + F_start_quat = 0x0200, F_start_scale = 0x0400, F_start_color = 0x0800, F_start_color_scale = 0x1000, @@ -87,6 +93,7 @@ private: unsigned int _flags; LPoint3f _start_pos, _end_pos; LVecBase3f _start_hpr, _end_hpr; + LQuaternionf _start_quat, _end_quat; LVecBase3f _start_scale, _end_scale; LVecBase3f _start_shear, _end_shear; Colorf _start_color, _end_color;