/*
 *      @(#)OrientationInterpolator.java 1.18 98/11/05 20:34:50
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

/*
 * @Author: Rick Goldberg
 * @Author: Doug Gehringer
 *
 */

package com.sun.j3d.loaders.vrml97.impl;
import javax.vecmath.*;

public class OrientationInterpolator extends Interpolator {

    // eventIn	
    SFFloat fraction;
    
    // exposedField
    // MFFloat key; // From Interpolator
    MFRotation keyValue;

    // eventOut

    SFRotation value;

    float[] v1,v2,currAxis;
    int i,j;

    boolean first=true;
    float oldVal;
    int boundIL=-1;
    boolean locDebug=false;
    AxisAngle4f axisAng1 = new AxisAngle4f();
    AxisAngle4f axisAng2 = new AxisAngle4f();
    Quat4f quat1 = new Quat4f();
    Quat4f quat2 = new Quat4f();
    
    public OrientationInterpolator(Loader loader) {
	super(loader);
	fraction = new SFFloat(0.0f);
	key = new MFFloat();
	keyValue = new MFRotation();
	value = new SFRotation(0.0f,0.0f,1.0f,0.0f);
	initFields();
    }

    
    OrientationInterpolator(Loader loader, MFFloat key, MFRotation keyValue) {
	super(loader);
	// initialize the interpolator to the right
	// value. otherwise do it manually;
	this.fraction = new SFFloat(0.0f);
	this.key = key;
	this.keyValue = keyValue;
	this.value = new SFRotation(0.0f,0.0f,1.0f,0.0f); 
	initFields();
    }
	    
    public void notifyMethod(String eventInName, double time) {
	if ( eventInName.equals("fraction") ) {
	    //System.out.println("OrientationInterpolator: fraction");
	    if (key.mfloat.length > 0) {
		setIndexFract(fraction.value);
		if (locDebug) System.out.println("OI(" + defName + "): " + "fraction.value = " + fraction.value + " iL = " + iL);

		v1 = keyValue.rots[iL].rot;
		v2 = keyValue.rots[iL+1].rot;

		// 03/21/00 Giles -- Changed to use Quaternions to do slerp
		axisAng1.set(v1);
		axisAng2.set(v2);
		quat1.set(axisAng1);
		quat2.set(axisAng2);
		double cosOmega = quat1.x*quat2.x + quat1.y*quat2.y + quat1.z*quat2.z + quat1.w * quat2.w;
		// If opposite hemispheres then negate quat1 -- Gems III pg 96
		if (cosOmega < 0.0) {
		    quat1.x *= -1;
		    quat1.y *= -1;
		    quat1.z *= -1;
		    quat1.w *= -1;
		}
		quat1.interpolate(quat2,f);
		axisAng1.set(quat1);
		axisAng1.get(value.rot);	
                if (locDebug) System.out.println("value: " + value.rot[0] + "," + value.rot[1] + "," + value.rot[2] + "," + value.rot[3]);
	    }
	    value.route();
	}
	    
    }

    public Object clone() {
	return new OrientationInterpolator(loader, (MFFloat)key.clone(), 
				(MFRotation)keyValue.clone() );
    }
    
    public String getType() { return "OrientationInterpolator"; }				
    void initFields() {
	fraction.init(this, FieldSpec, Field.EVENT_IN,      "fraction");
	key.init(     this, FieldSpec, Field.EXPOSED_FIELD, "key");
	keyValue.init(this, FieldSpec, Field.EXPOSED_FIELD, "keyValue");
	value.init(   this, FieldSpec, Field.EVENT_OUT,     "value");
    }

}


