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

com.jme3.bullet.objects.PhysicsGhostObject Maven / Gradle / Ivy

There is a newer version: 8.2.0+mt
Show newest version
/*
 * Copyright (c) 2009-2018 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.jme3.bullet.objects;

import com.jme3.bullet.collision.PcoType;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.util.clone.Cloner;
import com.simsilica.mathd.Matrix3d;
import com.simsilica.mathd.Quatd;
import com.simsilica.mathd.Vec3d;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jme3utilities.Validate;

/**
 * A collision object for intangibles, based on Bullet's
 * {@code btPairCachingGhostObject}. This is useful for creating a character
 * controller, collision sensors/triggers, explosions etc.
 * 

* Overlap detection skips the narrow-phase collision-detection algorithm and * relies entirely on the broad-phase algorithm, which is AABB plus a margin of * about 0.06 world units. Precise collision detection is still available via * {@code PhysicsSpace.addCollisionListener()}. *

* From Bullet manual:
* btGhostObject is a special btCollisionObject, useful for fast localized * collision queries. * * @author normenhansen */ public class PhysicsGhostObject extends PhysicsCollisionObject { // ************************************************************************* // constants and loggers /** * message logger for this class */ final public static Logger logger2 = Logger.getLogger(PhysicsGhostObject.class.getName()); /** * field names for serialization */ final private static String tagPhysicsLocation = "physicsLocation"; final private static String tagPhysicsRotation = "physicsRotation"; // ************************************************************************* // fields /** * TODO reused list */ private List overlappingObjects = new LinkedList<>(); // ************************************************************************* // constructors /** * No-argument constructor needed by SavableClassUtil. */ protected PhysicsGhostObject() { } /** * Instantiate a ghost object with the specified CollisionShape. The new * object is not added to any CollisionSpace. * * @param shape the desired shape (not null, alias created) */ public PhysicsGhostObject(CollisionShape shape) { super.setCollisionShape(shape); buildObject(); assert !isContactResponse(); } // ************************************************************************* // new methods exposed /** * Access an overlapping collision object by its position in the list. * Important: {@link #getOverlappingObjects()} must be invoked first! * * @param index which list position (≥0, <count) * @return the pre-existing object */ public PhysicsCollisionObject getOverlapping(int index) { PhysicsCollisionObject result = overlappingObjects.get(index); return result; } /** * Count how many collision objects this object overlaps. * * @return the count (≥0) */ public int getOverlappingCount() { long objectId = nativeId(); int result = getOverlappingCount(objectId); return result; } /** * Update and access a list of overlapping objects. * * @return an internal list which may get reused (not null) */ public List getOverlappingObjects() { overlappingObjects.clear(); long objectId = nativeId(); getOverlappingObjects(objectId); return overlappingObjects; } /** * Directly alter the location of the ghost's center. * * @param location the desired location (in physics-space coordinates, not * null, finite, unaffected) */ public void setPhysicsLocation(Vector3f location) { Validate.finite(location, "location"); long objectId = nativeId(); setPhysicsLocation(objectId, location); } /** * Directly alter the location of the ghost's center. * * @param location the desired location (in physics-space coordinates, not * null, unaffected) */ public void setPhysicsLocationDp(Vec3d location) { Validate.nonNull(location, "location"); long objectId = nativeId(); setPhysicsLocationDp(objectId, location); } /** * Directly alter the ghost's orientation. * * @param orientation the desired orientation (a rotation matrix in * physics-space coordinates, not null, unaffected) */ public void setPhysicsRotation(Matrix3f orientation) { Validate.nonNull(orientation, "orientation"); long objectId = nativeId(); setPhysicsRotation(objectId, orientation); } /** * Directly alter the ghost's orientation. * * @param orientation the desired orientation (a rotation quaternion in * physics-space coordinates, not null, not zero, unaffected) */ public void setPhysicsRotation(Quaternion orientation) { Validate.nonZero(orientation, "orientation"); long objectId = nativeId(); setPhysicsRotation(objectId, orientation); } /** * Directly alter the ghost's orientation. * * @param orientation the desired orientation (a rotation matrix in * physics-space coordinates, not null, unaffected) */ public void setPhysicsRotationDp(Matrix3d orientation) { Validate.nonNull(orientation, "orientation"); long objectId = nativeId(); setPhysicsRotationDp(objectId, orientation); } /** * Directly alter the ghost's orientation. * * @param orientation the desired orientation (a rotation quaternion in * physics-space coordinates, not null, unaffected) */ public void setPhysicsRotationDp(Quatd orientation) { Validate.nonNull(orientation, "orientation"); long objectId = nativeId(); setPhysicsRotationDp(objectId, orientation); } // ************************************************************************* // PhysicsCollisionObject methods /** * Callback from {@link com.jme3.util.clone.Cloner} to convert this * shallow-cloned object into a deep-cloned one, using the specified Cloner * and original to resolve copied fields. * * @param cloner the Cloner that's cloning this object (not null) * @param original the instance from which this object was shallow-cloned * (not null, unaffected) */ @Override public void cloneFields(Cloner cloner, Object original) { assert !hasAssignedNativeObject(); PhysicsGhostObject old = (PhysicsGhostObject) original; assert old != this; assert old.hasAssignedNativeObject(); super.cloneFields(cloner, original); if (hasAssignedNativeObject()) { return; } this.overlappingObjects = cloner.clone(overlappingObjects); buildObject(); copyPcoProperties(old); setPhysicsLocation(old.getPhysicsLocation(null)); setPhysicsRotation(old.getPhysicsRotationMatrix(null)); cloneIgnoreList(cloner, old); } /** * Apply the specified CollisionShape to this object. Note that the object * should not be in any CollisionSpace while changing shape; the object gets * rebuilt on the physics side. * * @param collisionShape the shape to apply (not null, alias created) */ @Override public void setCollisionShape(CollisionShape collisionShape) { super.setCollisionShape(collisionShape); buildObject(); } /** * De-serialize this object from the specified importer, for example when * loading from a J3O file. * * @param importer (not null) * @throws IOException from the importer */ @Override public void read(JmeImporter importer) throws IOException { super.read(importer); InputCapsule capsule = importer.getCapsule(this); buildObject(); readPcoProperties(capsule); setPhysicsLocation((Vector3f) capsule.readSavable( tagPhysicsLocation, new Vector3f())); setPhysicsRotation(((Matrix3f) capsule.readSavable( tagPhysicsRotation, new Matrix3f()))); } /** * Serialize this object to the specified exporter, for example when saving * to a J3O file. * * @param exporter (not null) * @throws IOException from the exporter */ @Override public void write(JmeExporter exporter) throws IOException { super.write(exporter); OutputCapsule capsule = exporter.getCapsule(this); capsule.write(getPhysicsLocation(null), tagPhysicsLocation, null); capsule.write(getPhysicsRotationMatrix(null), tagPhysicsRotation, null); } // ************************************************************************* // Java private methods /** * This method is invoked by native code. * * @param co the collision object to add (alias created) */ private void addOverlappingObject(PhysicsCollisionObject co) { overlappingObjects.add(co); } /** * Create the configured object in Bullet. */ private void buildObject() { if (!hasAssignedNativeObject()) { long objectId = createGhostObject(); setNativeId(objectId); assert getInternalType(objectId) == PcoType.ghost : getInternalType(objectId); logger2.log(Level.FINE, "Created {0}.", this); setGhostFlags(objectId); initUserPointer(); } long objectId = nativeId(); CollisionShape shape = getCollisionShape(); attachCollisionShape(objectId, shape.nativeId()); } // ************************************************************************* // native private methods native private static long createGhostObject(); native private static int getOverlappingCount(long objectId); native private void getOverlappingObjects(long objectId); native private static void setGhostFlags(long objectId); native private static void setPhysicsLocation(long objectId, Vector3f location); native private static void setPhysicsLocationDp(long objectId, Vec3d location); native private static void setPhysicsRotation(long objectId, Matrix3f rotation); native private static void setPhysicsRotation(long objectId, Quaternion rotation); native private static void setPhysicsRotationDp(long objectId, Matrix3d rotation); native private static void setPhysicsRotationDp(long objectId, Quatd rotation); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy