Quaternion
From Director Online Wiki
--*************************************************** --* QUATERNION --*************************************************** --* --* \file Quaternion.ls --* \brief Quaternion class, new data type. --* \author Maltus --* \version 1.1 --* \date 05/05/2009 --* \email -- --* \todo comment... --* --*************************************************** --* CONSTRUCTOR --*************************************************** --* --* <Quaternion> = script( <String> ).new() -- default --* <Quaternion> = script( <String> ).new( <List> ) -- <List> = <LinearList> / <PropList> / <AxisAngle> --* <Quaternion> = script( <String> ).new( <Transform> ) --* <Quaternion> = script( <String> ).new( <Vector> ) --* <Quaternion> = script( <String> ).new( <Quaternion> ) -- copy --* --*************************************************** --* PUBLIC METHODS --*************************************************** --* --* <Symbol> = <Quaternion>.ilk() / ilk( <Quaternion> ) --* <Boolean> = ilk( <Quaternion>, <Symbol> ) --* --* Predicate: --* <Boolean> = quaternionP( <Quaternion> ) --* --* Operator: direct access (.x, .y, .z, .w) and bracket access ([]) --* <Float> = getAt( <Integer> / <Symbol> / <String> ) --* <Float> = setAt( <Integer> / <Symbol> / <String>, <Number> ) --* --* <Void> = invert() --* <Void> = oppose() --* <Void> = normalize() --* <Void> = identity() --* --* <Quaternion> = duplicate() --* <Quaternion> = getInversed() --* <Quaternion> = getOpposed() --* <Quaternion> = getNormalized() --* --* <Quaternion> = multiply( <Quaternion> / <Transform> / <List> / <Vector> / <Number> ) --* <Quaternion> = add( <Quaternion> / <Transform> / <List> / <Vector> / <Number> ) --* <Quaternion> = subtract( <Quaternion> / <Transform> / <List> / <Vector> / <Number> ) --* --* <Boolean> = isEqualTo( <Quaternion> ) --* <Boolean> = isIdentity() --* <Boolean> = isNormalized() --* --* <Float> = dotProduct( <Quaternion> ) --* <Float> = magnitude() --* --* <Transform> = toTransform() --* <Vector> = toVector() --* <AxisAngle> = toAxisAngle() --* <PropList> = toPropList() --* <LinearList> = toLineList() --* <String> = toString() --* --* --*************************************************** --* PRIVATE METHODS --*************************************************** --* --* <Void> = __setQuaternion() --* <Void> = __setQuatFromTransform( <Transform> ) --* <Void> = __setQuatFromVector( <Vector> ) --* <Void> = __setQuatFromUndefList( <PropList> / <LinearList> / <AxisAngle> ) --* --* <Void> = __setPropListFromAxisAngle( <AxisAngle> ) --* <Void> = __listNormalize( <PropList> ) 'Optionnal' --* --* <Boolean> = __isAxisAngle( <AxisAngle> ) --* <Boolean> = __isLineList( <LinearList> ) --* <Boolean> = __isPropList( <PropList> ) --* --* <Float> = __arcCos( <Number> ) --* --* <Void> = __throwError( <PropList> ) --* <Void> = __throwPrivate() --* --* --*************************************************** -- Constant property DEGTORAD property RADTODEG property EPSILON -- Public property property quaternionP -- Private properties property ancestor property p_sScriptName --*************************************************** --* CONSTRUCTOR --*************************************************** --* --*************************************************** on new( me, aValue ) DEGTORAD = PI / float(180) RADTODEG = float(180) / PI EPSILON = 0.0001 -- __setQuaternion( VOID, me ) -- case ilk( aValue ) of #Void : nothing #Transform : __setQuatFromTransform( VOID, me, aValue ) #Vector : __setQuatFromVector( VOID, me, aValue ) #List : __setQuatFromUndefList( VOID, me, aValue ) #Quaternion: me.duplicate( aValue ) otherwise : __throwError( VOID, me, [#Error: "Value type mismatch !", #ID: "10505200901"] ) end case -- return( me ) end --*************************************************** --* GETAT --*************************************************** --* --*************************************************** on getAt( me, aProp ) -- case ilk( aProp ) of #Symbol : iPos = ([#x, #y, #z, #w]).getPos( aProp ) #String : iPos = ([#x, #y, #z, #w]).getPos( symbol( aProp ) ) #Integer : iPos = aProp otherwise: iPos = 0 end case -- if ( (iPos <= 0) OR (iPos > 4) ) then __throwError( VOID, me, [#Error: "Argument out of range !", #ID: "10505200902"] ) -- return( (me.ancestor)[iPos] ) end --*************************************************** --* SETAT --*************************************************** --* --*************************************************** on setAt( me, aProp, aValue ) -- case ilk( aProp ) of #Symbol : iPos = ([#x, #y, #z, #w]).getPos( aProp ) #String : iPos = ([#x, #y, #z, #w]).getPos( symbol( aProp ) ) #Integer : iPos = aProp otherwise: iPos = 0 end case -- if ( (iPos <= 0) OR (iPos > 4) ) then __throwError( VOID, me, [#Error: "Argument out of range !", #ID: "10505200903"] ) if not( ilk( aValue, #Number ) ) then __throwError( VOID, me, [#Error: "Number expected !", #ID: "10505200904"] ) (me.ancestor)[iPos] = float( aValue ) -- return( (me.ancestor)[iPos] ) end --*************************************************** --* ILK --*************************************************** --* --*************************************************** on ilk( me ) -- iCnt = _movie.paramCount() if (iCnt > 2) then __throwError( VOID, me, [#Error: "Wrong number of argument !", #ID: "10505200905"] ) -- if (iCnt = 1) then if integerP( me ) then return( #Integer ) if floatP( me ) then return( #Float ) if stringP( me ) then return( #String ) if symbolP( me ) then return( #Symbol ) if voidP( me ) then return( #Void ) if quaternionP( me ) then return( #Quaternion ) if (objectP( me ) AND not(listP( me ))) then return( #Object ) -- << must be after your own predicate ! __throwError( VOID, me, [#Error: "Unknown type !", #ID: "10505200906"] ) else case( _movie.param(iCnt) ) of #Integer : return( integerP( me ) ) #Float : return( floatP( me ) ) #Number : return( integerP( me ) OR floatP( me ) ) #String : return( stringP( me ) ) #Symbol : return( symbolP( me ) ) #Void : return( voidP( me ) ) #Quaternion: return( quaternionP( me ) ) #Object : return( (objectP( me ) AND not(listP( me ))) ) otherwise : return( FALSE ) end case end if -- end --*************************************************** --* QUATERNIONP --*************************************************** --* --*************************************************** on quaternionP( me ) -- if ( objectP( me ) AND not(listP( me )) ) then if not( voidP(me.getaProp(#p_sScriptName)) ) then if ( string( me ) contains (me.p_sScriptName) ) then return( TRUE ) end if end if end if -- return( FALSE ) end --*************************************************** --* INVERT --*************************************************** --* --*************************************************** on invert( me ) -- (me.ancestor)[1] = - (me.ancestor)[1] (me.ancestor)[2] = - (me.ancestor)[2] (me.ancestor)[3] = - (me.ancestor)[3] -- return end --*************************************************** --* OPPOSE --*************************************************** --* --*************************************************** on oppose( me ) -- me.ancestor = (me.ancestor) * float(-1) -- return end --*************************************************** --* NORMALIZE --*************************************************** --* --*************************************************** on normalize( me ) -- __listNormalize( VOID, me ) -- return end --*************************************************** --* IDENTITY --*************************************************** --* --*************************************************** on identity( me ) me.ancestor = [#x: float(0), #y: float(0), #z: float(0), #w: float(1)] return end --*************************************************** --* DUPLICATE --*************************************************** --* --*************************************************** on duplicate( me ) return( _movie.script( (me.p_sScriptName) ).new( me ) ) end --*************************************************** --* GETINVERSE --*************************************************** --* --*************************************************** on getInversed( me ) lInversed = ( (me.ancestor).duplicate() ) * float(-1) lInversed[4] = - lInversed[4] return( _movie.script( (me.p_sScriptName) ).new( lInversed ) ) end --*************************************************** --* GETOPPOSED --*************************************************** --* --*************************************************** on getOpposed( me ) lOpposed = ( (me.ancestor).duplicate() ) * float(-1) return( _movie.script( (me.p_sScriptName) ).new( lOpposed ) ) end --*************************************************** --* GETNORMALIZED --*************************************************** --* --*************************************************** on getNormalized( me ) lNormalized = (me.ancestor).duplicate() __listNormalize( VOID, me, lNormalized ) return( _movie.script( (me.p_sScriptName) ).new( lNormalized ) ) end --*************************************************** --* MULTIPLY --*************************************************** --* --*************************************************** on multiply( me, aValue ) -- case ilk( aValue ) of #Quaternion: lValue = (aValue.ancestor).duplicate() #Number : lValue = [#x: float(aValue), #y: float(aValue), #z: float(aValue), #w: float(aValue)] #Transform, #Vector, #List : lValue = (_movie.script( (me.p_sScriptName) ).new( aValue )).ancestor otherwise : __throwError( VOID, me, [#Error: "Value type mismatch !", #ID: "10505200907"] ) end case -- X1 = (me.ancestor)[1] Y1 = (me.ancestor)[2] Z1 = (me.ancestor)[3] W1 = (me.ancestor)[4] -- X2 = lValue[1] Y2 = lValue[2] Z2 = lValue[3] W2 = lValue[4] lValue = VOID -- return( _movie.script( (me.p_sScriptName) ).new( [\ W1 * X2 + X1 * W2 + Y1 * Z2 - Z1 * Y2,\ W1 * Y2 + Y1 * W2 + Z1 * X2 - X1 * Z2,\ W1 * Z2 + Z1 * W2 + X1 * Y2 - Y1 * X2,\ W1 * W2 - X1 * X2 - Y1 * Y2 - Z1 * Z2] ) ) end --*************************************************** --* ADD --*************************************************** --* --*************************************************** on add( me, aValue ) -- case ilk( aValue ) of #Quaternion: lValue = (aValue.ancestor).duplicate() #Number : lValue = [#x: float(aValue), #y: float(aValue), #z: float(aValue), #w: float(aValue)] #Transform, #Vector, #List : lValue = (_movie.script( (me.p_sScriptName) ).new( aValue )).ancestor otherwise : __throwError( VOID, me, [#Error: "Value type mismatch !", #ID: "10505200908"] ) end case -- X = (me.ancestor)[1] + lValue[1] Y = (me.ancestor)[2] + lValue[2] Z = (me.ancestor)[3] + lValue[3] W = (me.ancestor)[4] + lValue[4] lValue = VOID -- return( _movie.script( (me.p_sScriptName) ).new( [X, Y, Z, W] ) ) end --*************************************************** --* SUBTRACT --*************************************************** --* --*************************************************** on subtract( me, aValue ) -- case ilk( aValue ) of #Quaternion: lValue = (aValue.ancestor).duplicate() #Number : lValue = [#x: float(aValue), #y: float(aValue), #z: float(aValue), #w: float(aValue)] #Transform, #Vector, #List : lValue = (_movie.script( (me.p_sScriptName) ).new( aValue )).ancestor otherwise : __throwError( VOID, me, [#Error: "Value type mismatch !", #ID: "10505200909"] ) end case -- X = (me.ancestor)[1] - lValue[1] Y = (me.ancestor)[2] - lValue[2] Z = (me.ancestor)[3] - lValue[3] W = (me.ancestor)[4] - lValue[4] lValue = VOID -- return( _movie.script( (me.p_sScriptName) ).new( [X, Y, Z, W] ) ) end --*************************************************** --* ISEQUALTO --*************************************************** --* --*************************************************** on isEqualTo( me, aValue ) -- if not( ilk( aValue, #Quaternion ) ) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200910"] ) -- return(\ ( abs( (me.ancestor)[1] - (aValue.ancestor)[1] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[2] - (aValue.ancestor)[2] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[3] - (aValue.ancestor)[3] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[4] - (aValue.ancestor)[4] ) <= EPSILON ) ) end --*************************************************** --* ISIDENTITY --*************************************************** --* --*************************************************** on isIdentity( me ) -- if (\ ( abs( (me.ancestor)[1] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[2] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[3] ) <= EPSILON ) AND\ ( abs( (me.ancestor)[4] - float(1) ) <= EPSILON ) ) then return( TRUE ) -- return( FALSE ) end --*************************************************** --* ISNORMALIZED --*************************************************** --* --*************************************************** on isNormalized( me ) -- if ( abs( me.magnitude() - float(1) ) <= EPSILON ) then return( TRUE ) -- return( FALSE ) end --*************************************************** --* DOTPRODUCT --*************************************************** --* --*************************************************** on dotProduct( me, aValue ) -- if not( ilk( aValue, #Quaternion ) ) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200911"] ) -- return(\ ( (me.ancestor)[1] * aValue[1] ) + ( (me.ancestor)[2] * aValue[2] ) +\ ( (me.ancestor)[3] * aValue[3] ) + ( (me.ancestor)[4] * aValue[4] ) ) end --*************************************************** --* MAGNITUDE --*************************************************** --* --*************************************************** on magnitude( me ) -- return( sqrt(\ (me.ancestor)[1] * (me.ancestor)[1] +\ (me.ancestor)[2] * (me.ancestor)[2] +\ (me.ancestor)[3] * (me.ancestor)[3] +\ (me.ancestor)[4] * (me.ancestor)[4] ) ) end --*************************************************** --* TOTRANSFORM --*************************************************** --* --*************************************************** on toTransform( me ) -- __listNormalize( VOID, me ) -- X1 = (me.ancestor)[1] Y1 = (me.ancestor)[2] Z1 = (me.ancestor)[3] W1 = (me.ancestor)[4] -- X2 = X1 * X1 Y2 = Y1 * Y1 Z2 = Z1 * Z1 W2 = W1 * W1 -- XY = X1 * Y1 XZ = X1 * Z1 YZ = Y1 * Z1 -- WX = W1 * X1 WY = W1 * Y1 WZ = W1 * Z1 -- trsf = transform() -- trsf[1] = float( 1.0 - 2.0 * (Y2 + Z2) ) trsf[2] = float( 2.0 * (XY + WZ) ) trsf[3] = float( 2.0 * (XZ - WY) ) -- trsf[5] = float( 2.0 * (XY - WZ) ) trsf[6] = float( 1.0 - 2.0 * (X2 + Z2) ) trsf[7] = float( 2.0 * (YZ + WX) ) -- trsf[9] = float( 2.0 * (XZ + WY) ) trsf[10] = float( 2.0 * (YZ - WX) ) trsf[11] = float( 1.0 - 2.0 * (X2 + Y2) ) -- return( trsf ) end --*************************************************** --* TOVECTOR --*************************************************** --* --*************************************************** on toVector( me ) -- trsf = toTransform( me ) vEuler = trsf.rotation -- return( vEuler ) end --*************************************************** --* TOAXISANGLE --*************************************************** --* --*************************************************** on toAxisAngle( me ) -- __listNormalize( VOID, me ) -- X1 = (me.ancestor)[1] Y1 = (me.ancestor)[2] Z1 = (me.ancestor)[3] W1 = (me.ancestor)[4] -- fAngle = __arcCos( VOID, me, W1 ) fScale = me.magnitude() -- if ((0 <= fAngle) OR (PI >= fAngle)) then __throwError( VOID, me, [#Error: "Angle must be between 0 and PI !", #ID: "10505200912"] ) lAxisAngle = [] -- if ( fScale <= EPSILON ) then lAxisAngle.add( vector(1, 0, 0) ) lAxisAngle.add( float(0) ) else if ( (X1 = float(0)) AND (Y1 = float(0)) AND (Z1 = float(0)) ) then lAxisAngle.add( vector(1, 0, 0) ) lAxisAngle.add( float(0) ) else vEuler = vector( X1 / fScale, Y1 / fScale, Z1 / fScale ) vEuler.normalize() lAxisAngle.add( vEuler ) lAxisAngle.add( fAngle * float(2) * RADTODEG ) end if -- return( lAxisAngle ) end --*************************************************** --* TOPROPLIST --*************************************************** --* --*************************************************** on toPropList( me ) -- return( (me.ancestor).duplicate() ) end --*************************************************** --* TOLINELIST --*************************************************** --* --*************************************************** on toLineList( me ) -- return( [ (me.ancestor)[1], (me.ancestor)[2], (me.ancestor)[3], (me.ancestor)[4] ] ) end --*************************************************** --* TOSTRING --*************************************************** --* --*************************************************** on toString( me ) -- return( "Quaternion("&&"#x:"&&(me.ancestor)[1]&", #y:"&&(me.ancestor)[2]&", #z:"&&(me.ancestor)[3]&", #w:"&&(me.ancestor)[4]&&")" ) end --*************************************************** --* __SETQUATERNION --*************************************************** --* --*************************************************** on __setQuaternion( PRIVATE, me ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(objectP( me )) then __throwError( VOID, me, [#Error: "Object expected !", #ID: "10505200913"] ) -- sScript = string( me ) iWrdCnt = sScript.word.count iStrLgth = (sScript.word[2..iWrdCnt-2]).length me.p_sScriptName = (sScript.word[2..iWrdCnt]).char[2..(iStrLgth-1)] -- me.ancestor = [ #x: float(0), #y: float(0), #z: float(0), #w: float(1) ] QuaternionP = TRUE -- return end --*************************************************** --* __SETQUATFROMTRANSFORM --*************************************************** --* --*************************************************** on __setQuatFromTransform( PRIVATE, me, aTransform ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200914"] ) -- fTrace = 1 + aTransform[1] + aTransform[6] + aTransform[11] -- if ( fTrace > EPSILON ) then -- fRoot = sqrt( fTrace ) * float(2) (me.ancestor)[1] = ( aTransform[10] - aTransform[7] ) / fRoot (me.ancestor)[2] = ( aTransform[3] - aTransform[9] ) / fRoot (me.ancestor)[3] = ( aTransform[5] - aTransform[2] ) / fRoot (me.ancestor)[4] = 0.25 * fRoot -- else if ( (aTransform[1] > aTransform[6]) AND (aTransform[1] > aTransform[11]) ) then -- fRoot = sqrt( float(1) + aTransform[1] - aTransform[6] - aTransform[11] ) * float(2) (me.ancestor)[1] = 0.25 * fRoot (me.ancestor)[2] = ( aTransform[5] + aTransform[2] ) / fRoot (me.ancestor)[3] = ( aTransform[3] + aTransform[9] ) / fRoot (me.ancestor)[4] = ( aTransform[10] - aTransform[7] ) / fRoot -- else if ( aTransform[6] > aTransform[11] ) then -- fRoot = sqrt( float(1) + aTransform[6] - aTransform[1] - aTransform[11] ) * float(2) (me.ancestor)[1] = ( aTransform[5] + aTransform[2] ) / fRoot (me.ancestor)[2] = 0.25 * fRoot (me.ancestor)[3] = ( aTransform[10] + aTransform[7] ) / fRoot (me.ancestor)[4] = ( aTransform[3] - aTransform[9] ) / fRoot -- else -- fRoot = sqrt( float(1) + aTransform[11] - aTransform[1] - aTransform[6] ) * float(2) (me.ancestor)[1] = ( aTransform[3] + aTransform[9] ) / fRoot (me.ancestor)[2] = ( aTransform[10] + aTransform[7] ) / fRoot (me.ancestor)[3] = 0.25 * fRoot (me.ancestor)[4] = ( aTransform[5] - aTransform[2] ) / fRoot -- end if -- __listNormalize( VOID, me ) -- return end --*************************************************** --* __SETQUATFROMVECTOR --*************************************************** --* --*************************************************** on __setQuatFromVector( PRIVATE, me, aEuler ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200915"] ) -- X = (aEuler.x * DEGTORAD) * 0.5 Y = (aEuler.y * DEGTORAD) * 0.5 Z = (aEuler.z * DEGTORAD) * 0.5 -- fCosRoll = cos( X ) fCosPitch = cos( Y ) fCosYaw = cos( Z ) -- fSinRoll = sin( X ) fSinPitch = sin( Y ) fSinYaw = sin( Z ) -- fCosPitchCosYaw = fCosPitch * fCosYaw fSinPitchSinYaw = fSinPitch * fSinYaw -- (me.ancestor)[1] = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw (me.ancestor)[2] = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw (me.ancestor)[3] = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw (me.ancestor)[4] = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw -- __listNormalize( VOID, me ) -- return end --*************************************************** --* __SETQUATFROMUNDEFLIST --*************************************************** --* --*************************************************** on __setQuatFromUndefList( PRIVATE, me, aUndefList ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200916"] ) -- if ilk( aUndefList, #LinearList ) then iListCnt = aUndefList.count() iAxisAngle = 2 iLineList = 4 -- if ( iListCnt = iAxisAngle ) then if not( __isAxisAngle( VOID, me, aUndefList ) ) then __throwError( VOID, me, [#Error: "Axis angle expected !", #ID: "10505200917"] ) me.ancestor = __setPropListFromAxisAngle( VOID, me, aUndefList ) else if ( iListCnt = iLineList ) then if not( __isLineList( VOID, me, aUndefList ) ) then __throwError( VOID, me, [#Error: "Linear list expected !", #ID: "10505200918"] ) me.ancestor = [#x: float(aUndefList[1]), #y: float(aUndefList[2]), #z: float(aUndefList[3]), #w: float(aUndefList[4])] else __throwError( VOID, me, [#Error: "Undefined list !", #ID: "10505200919"] ) end if -- else if ilk( aUndefList, #PropList ) then if not( __isPropList( VOID, me, aUndefList ) ) then __throwError( VOID, me, [#Error: "Property list expected !", #ID: "10505200920"] ) me.ancestor = aUndefList.duplicate() -- end if -- aUndefList = VOID -- return end --*************************************************** --* __SETPROPLISTFROMAXISANGLE --*************************************************** --* --*************************************************** on __setPropListFromAxisAngle( PRIVATE, me, aAxisAngle ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200921"] ) -- vEuler = aAxisAngle[1].getNormalized() fTheta = aAxisAngle[2] * DEGTORAD fSin = sin( fTheta * 0.5 ) -- lProperty = [#x: float(0), #y: float(0), #z: float(0), #w: float(1)] lProperty.x = vEuler.x * fSin lProperty.y = vEuler.y * fSin lProperty.z = vEuler.z * fSin lProperty.w = cos( fTheta * 0.5 ) -- __listNormalize( VOID, me, lProperty ) -- return( lProperty ) end --*************************************************** --* __LISTNORMALIZE --*************************************************** -- --*************************************************** on __listNormalize( PRIVATE, me, aPropList ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200922"] ) if (voidP(aPropList)) then aPropList = me.ancestor -- fMagnitude = sqrt( aPropList[1] * aPropList[1] + aPropList[2] * aPropList[2] + aPropList[3] * aPropList[3] + aPropList[4] * aPropList[4] ) -- if ( fMagnitude < EPSILON ) then aPropList[1] = float(0) aPropList[2] = float(0) aPropList[3] = float(0) aPropList[4] = float(1) else fLength = float(1) / fMagnitude aPropList[1] = aPropList[1] * fLength aPropList[2] = aPropList[2] * fLength aPropList[3] = aPropList[3] * fLength aPropList[4] = aPropList[4] * fLength end if -- return end --*************************************************** --* __ISAXISANGLE --*************************************************** --* --*************************************************** on __isAxisAngle( PRIVATE, me, aAxisAngle ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200923"] ) -- if (not(ilk( aAxisAngle, #LinearList ))) then return( FALSE ) if ( aAxisAngle.count() <> 2 ) then return( FALSE ) if (not(ilk( aAxisAngle[1], #Vector ))) then return( FALSE ) if (not(ilk( aAxisAngle[2], #Number ))) then return( FALSE ) -- return( TRUE ) end --*************************************************** --* __ISLINELIST --*************************************************** --* --*************************************************** on __isLineList( PRIVATE, me, aLineList ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200924"] ) -- if not(ilk( aLineList, #LinearList )) then return( FALSE ) if ( aLineList.count() <> 4 ) then return( FALSE ) if not(ilk( aLineList[1], #Number )) then return( FALSE ) if not(ilk( aLineList[2], #Number )) then return( FALSE ) if not(ilk( aLineList[3], #Number )) then return( FALSE ) if not(ilk( aLineList[4], #Number )) then return( FALSE ) -- return( TRUE ) end --*************************************************** --* __ISPROPLIST --*************************************************** --* --*************************************************** on __isPropList( PRIVATE, me, aPropList ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200925"] ) -- if not(ilk( aPropList, #PropList )) then return( FALSE ) if ( aPropList.count() <> 4 ) then return( FALSE ) if ilk( aPropList.getaProp(#x), #VOID ) then return( FALSE ) if ilk( aPropList.getaProp(#y), #VOID ) then return( FALSE ) if ilk( aPropList.getaProp(#z), #VOID ) then return( FALSE ) if ilk( aPropList.getaProp(#w), #VOID ) then return( FALSE ) if not(ilk( aPropList.x, #Float )) then return( FALSE ) if not(ilk( aPropList.y, #Float )) then return( FALSE ) if not(ilk( aPropList.z, #Float )) then return( FALSE ) if not(ilk( aPropList.w, #Float )) then return( FALSE ) -- return( TRUE ) end --*************************************************** --* __ARCCOS --*************************************************** --* --*************************************************** on __arcCos( PRIVATE, me, x ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) if not(quaternionP( me )) then __throwError( VOID, me, [#Error: "Quaternion expected !", #ID: "10505200926"] ) -- x = float(x) -- if (x < float(0)) then return( PI + atan( sqrt( float(1) - (x * x) ) / x ) ) else if (x > 0) then return( atan( sqrt( float(1) - (x * x) ) / x ) ) else return( PI * 0.5 ) end if -- end --*************************************************** --* __THROWERROR --*************************************************** -- --*************************************************** on __throwError( PRIVATE, me, aErrorList ) -- if not(voidP( PRIVATE )) then __throwPrivate( VOID, me ) -- if ( ilk(_player.alertHook, #Object) AND (_system.environmentPropList[#runMode] = "Author") ) then -- _player.alert(...) else trace( "Error:"&&aErrorList.Error ) end if -- HALT -- return end --*************************************************** --* __THROWPRIVATE --*************************************************** -- --*************************************************** on __throwPrivate( PRIVATE, me ) -- if ( ilk(_player.alertHook, #Object) AND (_system.environmentPropList[#runMode] = "Author") ) then -- _player.alert(...) else trace( "Error: You couldn't access private method from your location !" ) end if -- HALT -- return end