All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.media.j3d.SharedGroupRetained Maven / Gradle / Ivy

/*
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

package javax.media.j3d;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;

/**
 * The SharedGroup node provides the ability to share a scene graph from
 * multiple other scene graphs through the use of a Link node.
 */

class SharedGroupRetained extends GroupRetained implements TargetsInterface {

    /*
    static final int ILLEGAL_LEAF_MASK =
                          1 << NodeRetained.BACKGROUND |
                          1 << NodeRetained.BEHAVIOR |
                          1 << NodeRetained.CLIP |
                          1 << NodeRetained.LINEARFOG |
                          1 << NodeRetained.EXPONENTIALFOG |
                          1 << NodeRetained.SOUNDSCAPE |
                          1 << NodeRetained.VIEWPLATFORM |
                          1 << NodeRetained.BOUNDINGLEAF;
    */

// The current list of child transform group nodes or link nodes
// under a transform group
ArrayList childTransformLinks = new ArrayList(1);

    // key which identifies a unique path from a
    // locale to this transform group
    HashKey currentKey = new HashKey();

    // key which identifies a unique path from a locale to this switch link
    HashKey switchKey = new HashKey();

/**
 * The Shared Group Node's parent vector.
 */
Vector parents = new Vector(1);

    // J3d copy.
    CachedTargets[] j3dCTs = null;

    // User copy.
    CachedTargets[] cachedTargets = null;

    // A bitmask of the types in targets for transform targets
    int localTargetThreads = 0;
    // combined localTargetThreads and decendants' localTargetThreads
    int targetThreads = 0;

    ArrayList switchStates = null;

    SharedGroupRetained() {
        this.nodeType = NodeRetained.SHAREDGROUP;
    }

    // SharedGroup specific data at SetLive.
    @Override
    void setAuxData(SetLiveState s, int index, int hkIndex) {
	int i, size;

	// Group's setAuxData()
	super.setAuxData(s, index, hkIndex);

	branchGroupPaths.add(hkIndex, s.branchGroupPaths.get(index));

        if (orderedPaths == null) {
            orderedPaths = new ArrayList(1);
        }
        orderedPaths.add(hkIndex, s.orderedPaths.get(index));

		if (switchStates == null) {
			switchStates = new ArrayList(1);
		}
        switchStates.add(hkIndex, s.switchStates.get(index));

	if (viewLists == null) {
	    viewLists = new ArrayList>(1);
	}
	// If there are some ViewSpecificGroups in the path above this SharedGroup
	//	System.err.println("====> hkIndex = "+hkIndex+" s.viewLists = "+s.viewLists);
	if (s.viewLists != null) {
	    viewLists.add(hkIndex, s.viewLists.get(index));
	}
	else {
	    viewLists.add(hkIndex, null);
	}

	if (lights == null) {
		lights = new ArrayList>(1);
	}
	if (s.lights != null) {
	    lights.add(hkIndex, s.lights.get(index));
	}
	else {
	    lights.add(hkIndex, null);
	}

	if (fogs == null) {
		fogs = new ArrayList>(1);
	}
	if (s.fogs != null) {
	    fogs.add(hkIndex, s.fogs.get(index));
	}
	else {
	    fogs.add(hkIndex, null);
	}


	if (modelClips == null) {
		modelClips = new ArrayList>(1);
	}
	if (s.modelClips != null) {
	    modelClips.add(hkIndex, s.modelClips.get(index));
	}
	else {
	    modelClips.add(hkIndex, null);
	}


	if (altAppearances == null) {
		altAppearances = new ArrayList>(1);
	}
	if (s.altAppearances != null) {
	    altAppearances.add(hkIndex, s.altAppearances.get(index));
	}
	else {
	    altAppearances.add(hkIndex, null);
	}
    }


    @Override
    void setNodeData(SetLiveState s) {

	// For inSharedGroup case.
	int i, j, len;

	if (localToVworld == null) {
	    localToVworld = new Transform3D[s.keys.length][];
	    localToVworldIndex = new int[s.keys.length][];
	    localToVworldKeys = new HashKey[s.keys.length];
            cachedTargets = new CachedTargets[s.keys.length];
	    len=0;
	}
	else {

	    int newLen = localToVworld.length + s.keys.length;

	    Transform3D newTList[][] = new Transform3D[newLen][];
	    HashKey newHList[] = new HashKey[newLen];
	    int newIndexList[][] = new int[newLen][];
            CachedTargets newTargets[] = new CachedTargets[newLen];

	    len = localToVworld.length;

	    // Copy the existing data into the newly created data objects.
	    System.arraycopy(localToVworld, 0, newTList, 0, localToVworld.length);
	    System.arraycopy(localToVworldIndex, 0, newIndexList, 0,
			     localToVworldIndex.length);
	    System.arraycopy(localToVworldKeys, 0, newHList, 0,
			     localToVworldKeys.length);
            System.arraycopy(cachedTargets, 0, newTargets, 0,
                             cachedTargets.length);

	    localToVworld = newTList;
	    localToVworldIndex = newIndexList;
	    localToVworldKeys = newHList;
            cachedTargets = newTargets;
	}

	int[] hkIndex = new int[1];
	int hkIndexPlus1, blkSize;

        s.hashkeyIndex = new int[s.keys.length];

	// This should appear before super.setNodeData() if it exists
	s.parentBranchGroupPaths = branchGroupPaths;

	for(i=len, j=0; i(1);
            orderedPaths = null;
            switchStates = null;
            cachedTargets = null;
            targetThreads = 0;
	    lights.clear();
	    fogs.clear();
	    modelClips.clear();
	    altAppearances.clear();
	}
	else {
	    int index, len;

	    // Remove the localToVworld key
	    int newLen = localToVworld.length - s.keys.length;

	    Transform3D[][] newTList = new Transform3D[newLen][];
	    HashKey[] newHList = new HashKey[newLen];
	    Transform3D newChildTList[][] = null;
	    int[][] newIndexList = new int[newLen][];
            CachedTargets[] newTargets = new CachedTargets[newLen];

	    int[] tempIndex = new int[s.keys.length];
	    int curStart =0, newStart =0;
	    boolean found = false;

	    for(i=0;i= 0) {
		    found = true;
		    if(index == curStart) {
			curStart++;
		    }
		    else {
			len = index - curStart;
			System.arraycopy(localToVworld, curStart, newTList, newStart, len);
			System.arraycopy(localToVworldIndex, curStart, newIndexList,
					 newStart, len);
			System.arraycopy(localToVworldKeys, curStart, newHList, newStart, len);
                        System.arraycopy(cachedTargets, curStart, newTargets,
                                         newStart, len);

			curStart = index+1;
			newStart = newStart + len;
		    }
		}
		else {
		    found = false;
		    MasterControl.getCoreLogger().severe("Can't Find matching hashKey in SG.removeNodeData.");
		}
	    }

	    if((found == true) && (curStart < localToVworld.length)) {
		len = localToVworld.length - curStart;
		System.arraycopy(localToVworld, curStart, newTList, newStart, len);
		System.arraycopy(localToVworldIndex, curStart, newIndexList,
				 newStart, len);
		System.arraycopy(localToVworldKeys, curStart, newHList, newStart, len);
                System.arraycopy(cachedTargets, curStart, newTargets,
                                 newStart, len);
	    }

	    // Must be in reverse, to preserve right indexing.
	    for (i = tempIndex.length-1; i >= 0 ; i--) {
		if(tempIndex[i] >= 0) {
		    branchGroupPaths.remove(tempIndex[i]);
                    orderedPaths.remove(tempIndex[i]);
                    switchStates.remove(tempIndex[i]);
		    lights.remove(tempIndex[i]);
		    fogs.remove(tempIndex[i]);
		    modelClips.remove(tempIndex[i]);
		    altAppearances.remove(tempIndex[i]);
		}
	    }

	    localToVworld = newTList;
	    localToVworldIndex = newIndexList;
	    localToVworldKeys = newHList;
            cachedTargets = newTargets;
	}
	s.localToVworld = localToVworld;
	s.localToVworldIndex = localToVworldIndex;
	s.localToVworldKeys = localToVworldKeys;
	s.orderedPaths = orderedPaths;
	s.switchStates = switchStates;
	s.viewLists = viewLists;
	s.lights = lights;
	s.fogs = fogs;
	s.modelClips = modelClips;
	s.altAppearances = altAppearances;
    }

    @Override
    void clearLive(SetLiveState s) {

        int i,j,k, index;

        Transform3D savedLocalToVworld[][] = s.localToVworld;
        int savedLocalToVworldIndex[][] = s.localToVworldIndex;
        HashKey savedLocalToVworldKeys[] = s.localToVworldKeys;
	ArrayList savedOrderedPaths = s.orderedPaths;
	ArrayList> savedViewLists = s.viewLists;

	ArrayList> savedLights = s.lights;
	ArrayList> savedFogs = s.fogs;
	ArrayList> savedMclips = s.modelClips;
	ArrayList> savedAltApps = s.altAppearances;

        Targets[] savedSwitchTargets = s.switchTargets;
        Targets[] savedTransformTargets = s.transformTargets;
        // no need to gather targets from sg in clear live
        s.transformTargets = null;
        s.switchTargets = null;


	// XXXX: This is a hack since removeNodeData is called before
	// children are clearLives
	int[] tempIndex = null;
	// Don't keep the indices if everything will be cleared
	if (s.keys.length != localToVworld.length) {
	    tempIndex = new int[s.keys.length];
	    for (i = s.keys.length-1; i >= 0; i--) {
		tempIndex[i] = s.keys[i].equals(localToVworldKeys, 0, localToVworldKeys.length);
	    }
	}

        super.clearLive(s);
	// Do this after children clearlive since part of the viewLists may get cleared
	// during removeNodeData
        if(refCount <= 0) {
	    viewLists.clear();
	}
	else {
	    // Must be in reverse, to preserve right indexing.
	    for (i = tempIndex.length-1; i >= 0 ; i--) {
		if(tempIndex[i] >= 0) {
		    viewLists.remove(tempIndex[i]);
		}
	    }
	}

        // restore setLiveState from it's local variables.
        // removeNodeData has altered these variables.
        s.localToVworld = savedLocalToVworld;
        s.localToVworldIndex = savedLocalToVworldIndex;
        s.localToVworldKeys = savedLocalToVworldKeys;
        s.orderedPaths = savedOrderedPaths;
        s.viewLists = savedViewLists;
	s.lights = savedLights;
	s.fogs = savedFogs;
	s.modelClips = savedMclips;
	s.altAppearances = savedAltApps;
        s.transformTargets = savedTransformTargets;
        s.switchTargets = savedSwitchTargets;
    }

    void updateChildLocalToVworld(HashKey key, int index,
                                  ArrayList dirtyTransformGroups,
                                        ArrayList keySet,
		                        UpdateTargets targets,
                                        ArrayList blUsers) {

        LinkRetained ln;
        TransformGroupRetained tg;
        int i,j;
	Object obj;

        CachedTargets ct = j3dCTs[index];
        if (ct != null) {
            targets.addCachedTargets(ct);
            if (ct.targetArr[Targets.BLN_TARGETS] != null) {
                gatherBlUsers(blUsers, ct.targetArr[Targets.BLN_TARGETS]);
            }
        }

        synchronized(childTransformLinks) {
        for (i=0; i updateList) {

        SwitchRetained sw;
        LinkRetained ln;
        Object obj;
	int i,j,k;

        ArrayList childSwitchLinks = childrenSwitchLinks.get(child);
        for (i=0; i>(1);
        }
        childrenSwitchLinks.add(index, new ArrayList(1));
    }

    @Override
    void appendChildrenData() {
        if (childrenSwitchLinks == null) {
            childrenSwitchLinks = new ArrayList>(1);
        }
        childrenSwitchLinks.add(new ArrayList(1));
    }

    @Override
    void removeChildrenData(int index) {
        ArrayList oldSwitchLinks = childrenSwitchLinks.get(index);
        oldSwitchLinks.clear();
        childrenSwitchLinks.remove(index);
    }


    // ***************************
    // TargetsInterface methods
    // ***************************

    @Override
    public int getTargetThreads(int type) {
	if (type == TargetsInterface.TRANSFORM_TARGETS) {
            return targetThreads;
        } else {
            System.err.println("getTargetThreads: wrong arguments");
	    return -1;
        }
    }

    @Override
    TargetsInterface getClosestTargetsInterface(int type) {
        return this;
    }

    // re-evalute localTargetThreads using newCachedTargets and
    // re-evaluate targetThreads
    @Override
    public void computeTargetThreads(int type,
					CachedTargets[] newCachedTargets) {

	localTargetThreads = 0;
	if (type == TargetsInterface.TRANSFORM_TARGETS) {
	    for(int i=0; i getTargetsData(int type, int index) {
	// index is ignores for SharedGroup
	if (type == TargetsInterface.SWITCH_TARGETS) {
		return switchStates;
	}
	else {
		System.err.println("getTargetsData: wrong arguments");
		return null;
	}
}

    @Override
    void childDoSetLive(NodeRetained child, int childIndex, SetLiveState s) {

	int i;
        s.childSwitchLinks = childrenSwitchLinks.get(childIndex);
        s.switchStates = switchStates;

        if(child!=null)
	    child.setLive(s);
    }

    void childCheckSetLive(NodeRetained child, int childIndex, SetLiveState s) {
        s.childTransformLinks = childTransformLinks;
        s.parentTransformLink = this;
        child.setLive(s);
    }

    /**
     * Make the boundsCache of this node and all its parents dirty
     */
    @Override
    void dirtyBoundsCache() {
        // Possible optimisation is to not traverse up the tree
        // if the cachedBounds==null. However this is not the case
        // if the node is the child of a SharedGroup
        if (VirtualUniverse.mc.cacheAutoComputedBounds) {
            // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
            validCachedBounds = false;
            synchronized(parents) {
                Enumeration e = parents.elements();
                while(e.hasMoreElements()) {
                    LinkRetained parent = (LinkRetained) e.nextElement();
                    if (parent!=null) {
                        parent.dirtyBoundsCache();
                    }
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy