1/*
2 * Copyright (c) 2009-2012 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33package com.jme3.bounding;
34
35import com.jme3.collision.Collidable;
36import com.jme3.export.JmeExporter;
37import com.jme3.export.JmeImporter;
38import com.jme3.export.Savable;
39import com.jme3.math.*;
40import java.io.IOException;
41import java.nio.FloatBuffer;
42
43/**
44 * <code>BoundingVolume</code> defines an interface for dealing with
45 * containment of a collection of points.
46 *
47 * @author Mark Powell
48 * @version $Id: BoundingVolume.java,v 1.24 2007/09/21 15:45:32 nca Exp $
49 */
50public abstract class BoundingVolume implements Savable, Cloneable, Collidable {
51
52    /**
53     * The type of bounding volume being used.
54     */
55    public enum Type {
56        /**
57         * {@link BoundingSphere}
58         */
59        Sphere,
60
61        /**
62         * {@link BoundingBox}.
63         */
64        AABB,
65
66        /**
67         * {@link com.jme3.bounding.OrientedBoundingBox}
68         */
69        OBB,
70
71        /**
72         * Currently unsupported by jME3.
73         */
74        Capsule;
75    }
76
77    protected int checkPlane = 0;
78    protected Vector3f center = new Vector3f();
79
80    public BoundingVolume() {
81    }
82
83    public BoundingVolume(Vector3f center) {
84        this.center.set(center);
85    }
86
87    /**
88     * Grabs the checkplane we should check first.
89     *
90     */
91    public int getCheckPlane() {
92        return checkPlane;
93    }
94
95    /**
96     * Sets the index of the plane that should be first checked during rendering.
97     *
98     * @param value
99     */
100    public final void setCheckPlane(int value) {
101        checkPlane = value;
102    }
103
104    /**
105     * getType returns the type of bounding volume this is.
106     */
107    public abstract Type getType();
108
109    /**
110     *
111     * <code>transform</code> alters the location of the bounding volume by a
112     * rotation, translation and a scalar.
113     *
114     * @param trans
115     *            the transform to affect the bound.
116     * @return the new bounding volume.
117     */
118    public final BoundingVolume transform(Transform trans) {
119        return transform(trans, null);
120    }
121
122    /**
123     *
124     * <code>transform</code> alters the location of the bounding volume by a
125     * rotation, translation and a scalar.
126     *
127     * @param trans
128     *            the transform to affect the bound.
129     * @param store
130     *            sphere to store result in
131     * @return the new bounding volume.
132     */
133    public abstract BoundingVolume transform(Transform trans, BoundingVolume store);
134
135    public abstract BoundingVolume transform(Matrix4f trans, BoundingVolume store);
136
137    /**
138     *
139     * <code>whichSide</code> returns the side on which the bounding volume
140     * lies on a plane. Possible values are POSITIVE_SIDE, NEGATIVE_SIDE, and
141     * NO_SIDE.
142     *
143     * @param plane
144     *            the plane to check against this bounding volume.
145     * @return the side on which this bounding volume lies.
146     */
147    public abstract Plane.Side whichSide(Plane plane);
148
149    /**
150     *
151     * <code>computeFromPoints</code> generates a bounding volume that
152     * encompasses a collection of points.
153     *
154     * @param points
155     *            the points to contain.
156     */
157    public abstract void computeFromPoints(FloatBuffer points);
158
159    /**
160     * <code>merge</code> combines two bounding volumes into a single bounding
161     * volume that contains both this bounding volume and the parameter volume.
162     *
163     * @param volume
164     *            the volume to combine.
165     * @return the new merged bounding volume.
166     */
167    public abstract BoundingVolume merge(BoundingVolume volume);
168
169    /**
170     * <code>mergeLocal</code> combines two bounding volumes into a single
171     * bounding volume that contains both this bounding volume and the parameter
172     * volume. The result is stored locally.
173     *
174     * @param volume
175     *            the volume to combine.
176     * @return this
177     */
178    public abstract BoundingVolume mergeLocal(BoundingVolume volume);
179
180    /**
181     * <code>clone</code> creates a new BoundingVolume object containing the
182     * same data as this one.
183     *
184     * @param store
185     *            where to store the cloned information. if null or wrong class,
186     *            a new store is created.
187     * @return the new BoundingVolume
188     */
189    public abstract BoundingVolume clone(BoundingVolume store);
190
191    public final Vector3f getCenter() {
192        return center;
193    }
194
195    public final Vector3f getCenter(Vector3f store) {
196        store.set(center);
197        return store;
198    }
199
200    public final void setCenter(Vector3f newCenter) {
201        center.set(newCenter);
202    }
203
204    /**
205     * Find the distance from the center of this Bounding Volume to the given
206     * point.
207     *
208     * @param point
209     *            The point to get the distance to
210     * @return distance
211     */
212    public final float distanceTo(Vector3f point) {
213        return center.distance(point);
214    }
215
216    /**
217     * Find the squared distance from the center of this Bounding Volume to the
218     * given point.
219     *
220     * @param point
221     *            The point to get the distance to
222     * @return distance
223     */
224    public final float distanceSquaredTo(Vector3f point) {
225        return center.distanceSquared(point);
226    }
227
228    /**
229     * Find the distance from the nearest edge of this Bounding Volume to the given
230     * point.
231     *
232     * @param point
233     *            The point to get the distance to
234     * @return distance
235     */
236    public abstract float distanceToEdge(Vector3f point);
237
238    /**
239     * determines if this bounding volume and a second given volume are
240     * intersecting. Intersecting being: one volume contains another, one volume
241     * overlaps another or one volume touches another.
242     *
243     * @param bv
244     *            the second volume to test against.
245     * @return true if this volume intersects the given volume.
246     */
247    public abstract boolean intersects(BoundingVolume bv);
248
249    /**
250     * determines if a ray intersects this bounding volume.
251     *
252     * @param ray
253     *            the ray to test.
254     * @return true if this volume is intersected by a given ray.
255     */
256    public abstract boolean intersects(Ray ray);
257
258
259    /**
260     * determines if this bounding volume and a given bounding sphere are
261     * intersecting.
262     *
263     * @param bs
264     *            the bounding sphere to test against.
265     * @return true if this volume intersects the given bounding sphere.
266     */
267    public abstract boolean intersectsSphere(BoundingSphere bs);
268
269    /**
270     * determines if this bounding volume and a given bounding box are
271     * intersecting.
272     *
273     * @param bb
274     *            the bounding box to test against.
275     * @return true if this volume intersects the given bounding box.
276     */
277    public abstract boolean intersectsBoundingBox(BoundingBox bb);
278
279    /**
280     * determines if this bounding volume and a given bounding box are
281     * intersecting.
282     *
283     * @param bb
284     *            the bounding box to test against.
285     * @return true if this volume intersects the given bounding box.
286     */
287//	public abstract boolean intersectsOrientedBoundingBox(OrientedBoundingBox bb);
288    /**
289     *
290     * determines if a given point is contained within this bounding volume.
291     * If the point is on the edge of the bounding volume, this method will
292     * return false. Use intersects(Vector3f) to check for edge intersection.
293     *
294     * @param point
295     *            the point to check
296     * @return true if the point lies within this bounding volume.
297     */
298    public abstract boolean contains(Vector3f point);
299
300    /**
301     * Determines if a given point intersects (touches or is inside) this bounding volume.
302     * @param point the point to check
303     * @return true if the point lies within this bounding volume.
304     */
305    public abstract boolean intersects(Vector3f point);
306
307    public abstract float getVolume();
308
309    @Override
310    public BoundingVolume clone() {
311        try{
312            BoundingVolume clone = (BoundingVolume) super.clone();
313            clone.center = center.clone();
314            return clone;
315        }catch (CloneNotSupportedException ex){
316            throw new AssertionError();
317        }
318    }
319
320    public void write(JmeExporter e) throws IOException {
321        e.getCapsule(this).write(center, "center", Vector3f.ZERO);
322    }
323
324    public void read(JmeImporter e) throws IOException {
325        center = (Vector3f) e.getCapsule(this).readSavable("center", Vector3f.ZERO.clone());
326    }
327
328}
329
330