/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* 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 'jMonkeyEngine' 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) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.aionemu.gameserver.geoEngine.scene;
import com.aionemu.gameserver.geoEngine.bounding.BoundingVolume;
import com.aionemu.gameserver.geoEngine.collision.Collidable;
import com.aionemu.gameserver.geoEngine.collision.CollisionIntention;
import com.aionemu.gameserver.geoEngine.math.Matrix3f;
import com.aionemu.gameserver.geoEngine.math.Vector3f;
/**
* <code>Spatial</code> defines the base class for scene graph nodes. It maintains a link to a parent, it's local
* transforms and the world's transforms. All other nodes, such as <code>Node</code> and <code>Geometry</code> are
* subclasses of <code>Spatial</code>.
*
* @author Mark Powell
* @author Joshua Slack
* @author Rolandas - added materials
* @version $Revision: 4075 $, $Data$
*/
public abstract class Spatial implements Collidable, Cloneable {
public enum CullHint {
/**
* Do whatever our parent does. If no parent, we'll default to dynamic.
*/
Inherit,
/**
* Do not draw if we are not at least partially within the view frustum of the renderer's camera.
*/
Dynamic,
/**
* Always cull this from view.
*/
Always,
/**
* Never cull this from view. Note that we will still get culled if our parent is culled.
*/
Never;
}
/**
* Spatial's bounding volume relative to the world.
*/
protected BoundingVolume worldBound;
/**
* This spatial's name.
*/
protected String name;
/**
* Spatial's parent, or null if it has none.
*/
protected transient Node parent;
/**
* Do not use this constructor. Serialization purposes only.
*/
protected Spatial() {
this(null);
}
/**
* Constructor instantiates a new <code>Spatial</code> object setting the rotation, translation and scale value to
* defaults.
*
* @param name
* the name of the scene element. This is required for identification and comparision purposes.
*/
public Spatial(String name) {
this.name = name;
}
/**
* Sets the name of this spatial.
*
* @param name
* The spatial's new name.
*/
public void setName(String name) {
if (name != null)
this.name = name;
}
/**
* Returns the name of this spatial.
*
* @return This spatial's name.
*/
public String getName() {
return name;
}
/**
* <code>getParent</code> retrieve's this node's parent. If the parent is null this is the root node.
*
* @return the parent of this node.
*/
public Node getParent() {
return parent;
}
/**
* Called by {@link Node#attachChild(Spatial)} and {@link Node#detachChild(Spatial)} - don't call directly.
* <code>setParent</code> sets the parent of this node.
*
* @param parent
* the parent of this node.
*/
protected void setParent(Node parent) {
this.parent = parent;
}
/**
* <code>removeFromParent</code> removes this Spatial from it's parent.
*
* @return true if it has a parent and performed the remove.
*/
public boolean removeFromParent() {
if (parent != null) {
parent.detachChild(this);
return true;
}
return false;
}
/**
* determines if the provided Node is the parent, or parent's parent, etc. of this Spatial.
*
* @param ancestor
* the ancestor object to look for.
* @return true if the ancestor is found, false otherwise.
*/
public boolean hasAncestor(Node ancestor) {
if (parent == null) {
return false;
} else if (parent.equals(ancestor)) {
return true;
} else {
return parent.hasAncestor(ancestor);
}
}
/**
* <code>updateModelBound</code> recalculates the bounding object for this Spatial.
*/
public abstract void updateModelBound();
/**
* <code>setModelBound</code> sets the bounding object for this Spatial.
*
* @param modelBound
* the bounding object for this spatial.
*/
public abstract void setModelBound(BoundingVolume modelBound);
/**
* @return The sum of all verticies under this Spatial.
*/
public abstract int getVertexCount();
/**
* @return The sum of all triangles under this Spatial.
*/
public abstract int getTriangleCount();
public abstract void setCollisionIntentions(byte collisionIntentions);
public abstract void setMaterialId(byte materialId);
public abstract byte getCollisionIntentions();
public abstract int getMaterialId();
/**
* Note that we are <i>matching</i> the pattern, therefore the pattern must match the entire pattern (i.e. it behaves
* as if it is sandwiched between "^" and "$"). You can set regex modes, like case insensitivity, by using the (?X) or
* (?X:Y) constructs.
*
* @param spatialSubclass
* Subclass which this must implement. Null causes all Spatials to qualify.
* @param nameRegex
* Regular expression to match this name against. Null causes all Names to qualify.
* @return true if this implements the specified class and this's name matches the specified pattern.
* @see java.util.regex.Pattern
*/
public boolean matches(Class<? extends Spatial> spatialSubclass, String nameRegex) {
if (spatialSubclass != null && !spatialSubclass.isInstance(this))
return false;
if (nameRegex != null && (name == null || !name.matches(nameRegex)))
return false;
return true;
}
/**
* <code>getWorldBound</code> retrieves the world bound at this node level.
*
* @return the world bound at this level.
*/
public BoundingVolume getWorldBound() {
return worldBound;
}
/**
* Returns the Spatial's name followed by the class of the spatial <br>
* Example: "MyNode (com.jme3.scene.Spatial)
*
* @return Spatial's name followed by the class of the Spatial
*/
@Override
public String toString() {
return name + " (" + this.getClass().getSimpleName() + ") use " + CollisionIntention.toString(getCollisionIntentions());
}
public abstract void setTransform(Matrix3f rotation, Vector3f loc, Vector3f scale);
@Override
public Spatial clone() throws CloneNotSupportedException {
return (Spatial) super.clone();
}
}