/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2004, by :
* Corporate:
* Astrium SAS
* Individual:
* Claude Cazenave
*
* $Id: TransformData.java,v 1.10 2005/11/02 18:06:37 ogor Exp $
*
* Changes
* -------
* 17-Jan-2004 : Creation date (CC);
*
*/
package syn3d.data;
import java.io.Serializable;
import java.util.ArrayList;
import javax.vecmath.Matrix3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;
import simtools.data.DataSource;
import syn3d.nodes.TransformGroupNode;
/**
* Class description ...
*
* @author Claude CAZENAVE
*
*/
public abstract class TransformData extends SceneGraphFloatData implements Serializable {
static final long serialVersionUID = -759797721505501385L;
public static final int IDENTITY=1;
public static final int TRANSX=2;
public static final int TRANSY=3;
public static final int TRANSZ=4;
public static final int TRANSXYZ=5;
public static final int ROTX=6;
public static final int ROTY=7;
public static final int ROTZ=8;
public static final int ROTXYZ=9;
public static final int SCALEX=10;
public static final int SCALEY=11;
public static final int SCALEZ=12;
public static final int SCALE=13;
public static final int SCALEXYZ=14;
public static final int AFFINE=15;
public static final int FULL=16;
protected int kind;
protected transient TransformGroupNode node;
protected ArrayList transformChildren; // composed transformations
protected TransformData transformRoot; // root of the transformation
protected static final int[] PARAM_SIZE={
-1, 0,
1, 1, 1, 3,
1, 1, 1, 4,
1, 1, 1, 1, 3,
9, 16
};
/**
* @param node2
*/
public TransformData(TransformGroupNode node) {
this.node = node;
transformChildren = new ArrayList();
transformRoot = this;
}
public TransformData(TransformGroupNode node, TransformData transformRoot) {
this.node = node;
transformChildren = new ArrayList();
this.transformRoot = transformRoot;
setDelegateListener(transformRoot.getDelegateListener());
}
public void restoreTransform(TransformGroupNode node){
this.node = node;
for(int i=transformChildren.size()-1; i>=0; i--){
((TransformData)transformChildren.get(i)).restoreTransform(node,transformRoot);
}
}
/**
* Restore composed sub transformation
* @param node
* @param transformRoot
*/
public void restoreTransform(TransformGroupNode node, TransformData transformRoot){
this.node = node;
this.transformRoot = transformRoot;
setDelegateListener(transformRoot.getDelegateListener());
}
/**
* @param i
*/
public void setKind(int i){
init(i,!editable);
}
/**
* @return Returns the kind.
*/
public int getKind() {
return kind;
}
public void init(){
init(-1, !editable);
}
protected abstract void init(int preferredKind, boolean fromNode);
public static boolean isIdentity(Matrix4f m4){
return m4.m00==1.f
&& m4.m11==1.f
&& m4.m22==1.f
&& m4.m33==1.f
&& m4.m01==0.f
&& m4.m02==0.f
&& m4.m03==0.f
&& m4.m10==0.f
&& m4.m12==0.f
&& m4.m13==0.f
&& m4.m20==0.f
&& m4.m21==0.f
&& m4.m23==0.f
&& m4.m30==0.f
&& m4.m31==0.f
&& m4.m32==0.f;
}
public static boolean isIdentity(Matrix3f m3){
return m3.m00==1.f
&& m3.m11==1.f
&& m3.m22==1.f
&& m3.m01==0.f
&& m3.m02==0.f
&& m3.m10==0.f
&& m3.m12==0.f
&& m3.m20==0.f
&& m3.m21==0.f;
}
public static int getKind(Matrix4f m){
if (m.m03 != 0.f
|| m.m13 != 0.f
|| m.m23 != 0.f
|| m.m33 != 1.0
|| m.m30 != 0.f
|| m.m31 != 0.f
|| m.m32 != 0.f) {
return FULL;
}
if(isIdentity(m)){
return IDENTITY;
}
Matrix3f m3=new Matrix3f();
Vector3f v=new Vector3f();
float s=m.get(m3, v);
if(s==1.0f){
if(isIdentity(m3)){
if(v.x==0.f){
if(v.y==0.f){
return TRANSZ;
}
else{
if(v.z==0.f){
return TRANSY;
}
}
}
else if(v.y==0.f && v.z==0.f){
return TRANSX;
}
return TRANSXYZ;
}
else if(v.lengthSquared()==0.f){
Quat4f q=new Quat4f();
m.get(q);
if(q.x==0.f){
if(q.y==0.f){
return ROTZ;
}
else if(q.z==0.f){
return ROTY;
}
}
else if(q.y==0.f && q.z==0.f){
return ROTX;
}
return ROTXYZ;
}
}
else if(v.lengthSquared()==0.f){
if(isIdentity(m3)){
if(m.m00==m.m11 && m.m11==m.m22){
return SCALE;
}
if(m.m00==1.f){
if(m.m11==1.f){
return SCALEZ;
}
else if(m.m22==1.f){
return SCALEY;
}
}
else if(m.m11==1.f && m.m22==1.f){
return SCALEX;
}
}
}
return AFFINE;
}
/* (non-Javadoc)
* @see syn3d.data.SceneGraphFloatData#set(float[], simtools.data.DataSource[])
*/
public void set(int kind, float[] values, DataSource[] d) {
this.kind = kind;
super.set(values, d);
}
/* (non-Javadoc)
* @see syn3d.data.SceneGraphData#updateFrom(syn3d.data.SceneGraphData)
*/
public void updateFrom(SceneGraphData dataCopy) {
super.updateFrom(dataCopy);
if (transformRoot==this){
for(int i=0; i<transformChildren.size(); i++){
( (TransformData)transformChildren.get(i)).removeSceneGraphData();
}
transformChildren.clear();
for(int i=0; i< ((TransformData)dataCopy).getTransformChildren().size(); i++){
TransformData newTransform = addComposedTransformation();
newTransform.transformRoot = this;
newTransform.updateFrom( (TransformData) ((TransformData)dataCopy).getTransformChildren().get(i));
}
}
kind = ((TransformData)dataCopy).kind;
updateTransform();
}
public Object clone() throws CloneNotSupportedException{
TransformData res = (TransformData)super.clone();
if (transformRoot==this){
res.transformRoot = res;
res.transformChildren = new ArrayList(transformChildren.size());
for(int i=0; i<transformChildren.size(); i++){
res.transformChildren.add( ((TransformData)transformChildren.get(i)).clone());
}
for(int i=0; i<res.transformChildren.size(); i++){
( (TransformData)res.transformChildren.get(i)).transformRoot = res;
}
}
return res;
}
/**
* Apply current data values to the associated transformation
*/
public void updateTransform() {
// subclasses should do this according to their underlying 3D model
}
/* (non-Javadoc)
* @see simtools.data.DataSourceListener#DataSourceIndexRangeChanged(simtools.data.DataSource, long, long)
*/
public void DataSourceIndexRangeChanged(DataSource ds, long startIndex, long lastIndex) {
super.DataSourceIndexRangeChanged(ds, startIndex, lastIndex);
if (node!=null) node.setDirty();
}
/* (non-Javadoc)
* @see simtools.data.DataSourceListener#DataSourceValueChanged(simtools.data.DataSource, long, long)
*/
public void DataSourceValueChanged(DataSource ds, long minIndex,
long maxIndex) {
super.DataSourceValueChanged(ds, minIndex, maxIndex);
if (node!=null) node.setDirty();
}
/* (non-Javadoc)
* @see syn3d.data.SceneGraphData#dispose()
*/
public void dispose() {
super.dispose();
if (transformRoot==this){
for(int i=0; i<transformChildren.size(); i++){
((TransformData)transformChildren.get(i)).dispose();
}
}
}
/* (non-Javadoc)
* @see syn3d.data.SceneGraphData#removeSceneGraphData()
*/
public void removeSceneGraphData(){
super.removeSceneGraphData();
if (transformRoot==this){
for(int i=0; i<transformChildren.size(); i++){
((TransformData)transformChildren.get(i)).removeSceneGraphData();
}
}
}
// Composed transformation
public boolean isComposed(){
return (transformChildren.size()!=0);
}
public ArrayList getTransformChildren(){
return transformChildren;
}
public abstract TransformData addComposedTransformation();
public abstract void removeLastComposedTransformation();
}