/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.scenegraph.utils; import java.util.Stack; import org.openmali.vecmath2.Matrix4f; import org.xith3d.scenegraph.*; import org.xith3d.scenegraph.traversal.DetailedTraversalCallback; /** * Clones a Subtree of the scenegraph. * * @author Marvin Froehlich (aka Qudus) */ public class TreeCloner implements DetailedTraversalCallback { private final Stack< GroupNode > nodeStack = new Stack< GroupNode >(); private GroupNode root = null; private boolean deepCopy = false; public boolean isDeepCopy() { return deepCopy; } public void setDeepCopy(boolean deepCopy) { this.deepCopy = deepCopy; } protected final void add( Node node ) { if ( !nodeStack.isEmpty() ) { nodeStack.peek().addChild( node ); } if ( node instanceof GroupNode ) { nodeStack.push( (GroupNode)node ); if ( root == null ) { this.root = (GroupNode)node; } } } /** * {@inheritDoc} */ public boolean traversalOperationCommon( Node node ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationCommon( GroupNode node ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroupCommon( GroupNode group ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroup( BranchGroup bg ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroup( Group group ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroup( Switch sw ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroup( TransformGroup tg ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalCheckGroup( OrderedGroup og ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Node node ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( BranchGroup bg ) { add( new BranchGroup() ); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Group group ) { add( new Group() ); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( TransformGroup tg ) { if (tg instanceof Transform) { Transform t = new Transform(); t.setMatrix(tg.getTransform().getMatrix4f()); add (t); } else { add(new TransformGroup(tg.getTransform())); } return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( OrderedGroup og ) { add( new OrderedGroup() ); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Switch sw ) { add( new Switch( sw.getWhichChild() ) ); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Shape3D shape ) { Shape3D newShape = null; if (deepCopy) { newShape = new Shape3D(shape.getGeometry().cloneNodeComponent(true), shape.getAppearance().cloneNodeComponent(true)); } else { newShape = new Shape3D(shape.getGeometry(),shape.getAppearance()); } newShape.setName(shape.getName()); add( newShape ); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Light light ) { if ( light instanceof DirectionalLight ) { final DirectionalLight dirLight = (DirectionalLight)light; add( new DirectionalLight( dirLight.isEnabled(), dirLight.getColor(), dirLight.getDirection() ) ); } else if ( light instanceof SpotLight ) { final SpotLight spotLight = (SpotLight)light; add( new SpotLight( spotLight.isEnabled(), spotLight.getColor(), spotLight.getLocation(), spotLight.getAttenuation(), spotLight.getDirection(), spotLight.getSpreadAngle(), spotLight.getConcentration() ) ); } else if ( light instanceof PointLight ) { final PointLight pointLight = (PointLight)light; add( new PointLight( pointLight.isEnabled(), pointLight.getColor(), pointLight.getLocation(), pointLight.getAttenuation() ) ); } else { throw new Error( light.getClass().getName() + " is not yet supported for cloning." ); } return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Fog fog ) { if ( fog instanceof LinearFog ) { final LinearFog linFog = (LinearFog)fog; add( new LinearFog( linFog.getColor(), linFog.getFrontDistance(), linFog.getBackDistance() ) ); } else if ( fog instanceof ExponentialFog ) { final ExponentialFog expFog = (ExponentialFog)fog; add( new ExponentialFog( expFog.getColor(), expFog.getDensity() ) ); } else { throw new Error( fog.getClass().getName() + " is not yet supported for cloning." ); } return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperation( Sound sound ) { if ( sound instanceof BackgroundSound ) { final BackgroundSound bgSound = (BackgroundSound)sound; add( new BackgroundSound( bgSound.getSoundContainer(), bgSound.getInitialGain() ) ); } else if ( sound instanceof PointSound ) { final PointSound pSound = (PointSound)sound; add( new PointSound( pSound.getSoundContainer(), pSound.getInitialGain() ) ); } else { throw new Error( sound.getClass().getName() + " is not yet supported for cloning." ); } return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationCommonAfter( Node node ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationCommonAfter( GroupNode group ) { nodeStack.pop(); return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( BranchGroup bg ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Group group ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( TransformGroup tg ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( OrderedGroup og ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Node node ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Switch sw ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Shape3D shape ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Light light ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Fog fog ) { return ( true ); } /** * {@inheritDoc} */ public boolean traversalOperationAfter( Sound sound ) { return ( true ); } @SuppressWarnings("unchecked") public < GroupNodeExtension extends GroupNode > GroupNodeExtension cloneTree( GroupNodeExtension root ) { this.root = null; this.nodeStack.clear(); root.traverse( this ); final GroupNodeExtension result = (GroupNodeExtension)this.root; this.root = null; this.nodeStack.clear(); return ( result ); } public TreeCloner() { } }