1/* 2 * Copyright (c) 2009-2010 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 */ 32package com.jme3.bullet.collision.shapes; 33 34import com.bulletphysics.collision.shapes.CompoundShape; 35import com.bulletphysics.linearmath.Transform; 36import com.jme3.bullet.collision.shapes.infos.ChildCollisionShape; 37import com.jme3.bullet.util.Converter; 38import com.jme3.export.InputCapsule; 39import com.jme3.export.JmeExporter; 40import com.jme3.export.JmeImporter; 41import com.jme3.export.OutputCapsule; 42import com.jme3.math.Matrix3f; 43import com.jme3.math.Vector3f; 44import java.io.IOException; 45import java.util.ArrayList; 46import java.util.Iterator; 47import java.util.List; 48import java.util.logging.Level; 49import java.util.logging.Logger; 50 51/** 52 * A CompoundCollisionShape allows combining multiple base shapes 53 * to generate a more sophisticated shape. 54 * @author normenhansen 55 */ 56public class CompoundCollisionShape extends CollisionShape { 57 58 protected ArrayList<ChildCollisionShape> children = new ArrayList<ChildCollisionShape>(); 59 60 public CompoundCollisionShape() { 61 cShape = new CompoundShape(); 62 } 63 64 /** 65 * adds a child shape at the given local translation 66 * @param shape the child shape to add 67 * @param location the local location of the child shape 68 */ 69 public void addChildShape(CollisionShape shape, Vector3f location) { 70 Transform transA = new Transform(Converter.convert(new Matrix3f())); 71 Converter.convert(location, transA.origin); 72 children.add(new ChildCollisionShape(location.clone(), new Matrix3f(), shape)); 73 ((CompoundShape) cShape).addChildShape(transA, shape.getCShape()); 74 } 75 76 /** 77 * adds a child shape at the given local translation 78 * @param shape the child shape to add 79 * @param location the local location of the child shape 80 */ 81 public void addChildShape(CollisionShape shape, Vector3f location, Matrix3f rotation) { 82 if(shape instanceof CompoundCollisionShape){ 83 throw new IllegalStateException("CompoundCollisionShapes cannot have CompoundCollisionShapes as children!"); 84 } 85 Transform transA = new Transform(Converter.convert(rotation)); 86 Converter.convert(location, transA.origin); 87 Converter.convert(rotation, transA.basis); 88 children.add(new ChildCollisionShape(location.clone(), rotation.clone(), shape)); 89 ((CompoundShape) cShape).addChildShape(transA, shape.getCShape()); 90 } 91 92 private void addChildShapeDirect(CollisionShape shape, Vector3f location, Matrix3f rotation) { 93 if(shape instanceof CompoundCollisionShape){ 94 throw new IllegalStateException("CompoundCollisionShapes cannot have CompoundCollisionShapes as children!"); 95 } 96 Transform transA = new Transform(Converter.convert(rotation)); 97 Converter.convert(location, transA.origin); 98 Converter.convert(rotation, transA.basis); 99 ((CompoundShape) cShape).addChildShape(transA, shape.getCShape()); 100 } 101 102 /** 103 * removes a child shape 104 * @param shape the child shape to remove 105 */ 106 public void removeChildShape(CollisionShape shape) { 107 ((CompoundShape) cShape).removeChildShape(shape.getCShape()); 108 for (Iterator<ChildCollisionShape> it = children.iterator(); it.hasNext();) { 109 ChildCollisionShape childCollisionShape = it.next(); 110 if (childCollisionShape.shape == shape) { 111 it.remove(); 112 } 113 } 114 } 115 116 public List<ChildCollisionShape> getChildren() { 117 return children; 118 } 119 120 /** 121 * WARNING - CompoundCollisionShape scaling has no effect. 122 */ 123 @Override 124 public void setScale(Vector3f scale) { 125 Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CompoundCollisionShape cannot be scaled"); 126 } 127 128 public void write(JmeExporter ex) throws IOException { 129 super.write(ex); 130 OutputCapsule capsule = ex.getCapsule(this); 131 capsule.writeSavableArrayList(children, "children", new ArrayList<ChildCollisionShape>()); 132 } 133 134 public void read(JmeImporter im) throws IOException { 135 super.read(im); 136 InputCapsule capsule = im.getCapsule(this); 137 children = capsule.readSavableArrayList("children", new ArrayList<ChildCollisionShape>()); 138 cShape.setLocalScaling(Converter.convert(getScale())); 139 cShape.setMargin(margin); 140 loadChildren(); 141 } 142 143 private void loadChildren() { 144 for (Iterator<ChildCollisionShape> it = children.iterator(); it.hasNext();) { 145 ChildCollisionShape child = it.next(); 146 addChildShapeDirect(child.shape, child.location, child.rotation); 147 } 148 } 149 150} 151