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 */ 32 33 package com.jme3.math; 34 35 import com.jme3.export.*; 36 import java.io.IOException; 37 38 39 /** 40 * <code>Ring</code> defines a flat ring or disk within three dimensional 41 * space that is specified via the ring's center point, an up vector, an inner 42 * radius, and an outer radius. 43 * 44 * @author Andrzej Kapolka 45 * @author Joshua Slack 46 */ 47 48 public final class Ring implements Savable, Cloneable, java.io.Serializable { 49 50 static final long serialVersionUID = 1; 51 52 private Vector3f center, up; 53 private float innerRadius, outerRadius; 54 private transient static Vector3f b1 = new Vector3f(), b2 = new Vector3f(); 55 56 /** 57 * Constructor creates a new <code>Ring</code> lying on the XZ plane, 58 * centered at the origin, with an inner radius of zero and an outer radius 59 * of one (a unit disk). 60 */ Ring()61 public Ring() { 62 center = new Vector3f(); 63 up = Vector3f.UNIT_Y.clone(); 64 innerRadius = 0f; 65 outerRadius = 1f; 66 } 67 68 /** 69 * Constructor creates a new <code>Ring</code> with defined center point, 70 * up vector, and inner and outer radii. 71 * 72 * @param center 73 * the center of the ring. 74 * @param up 75 * the unit up vector defining the ring's orientation. 76 * @param innerRadius 77 * the ring's inner radius. 78 * @param outerRadius 79 * the ring's outer radius. 80 */ Ring(Vector3f center, Vector3f up, float innerRadius, float outerRadius)81 public Ring(Vector3f center, Vector3f up, float innerRadius, 82 float outerRadius) { 83 this.center = center; 84 this.up = up; 85 this.innerRadius = innerRadius; 86 this.outerRadius = outerRadius; 87 } 88 89 /** 90 * <code>getCenter</code> returns the center of the ring. 91 * 92 * @return the center of the ring. 93 */ getCenter()94 public Vector3f getCenter() { 95 return center; 96 } 97 98 /** 99 * <code>setCenter</code> sets the center of the ring. 100 * 101 * @param center 102 * the center of the ring. 103 */ setCenter(Vector3f center)104 public void setCenter(Vector3f center) { 105 this.center = center; 106 } 107 108 /** 109 * <code>getUp</code> returns the ring's up vector. 110 * 111 * @return the ring's up vector. 112 */ getUp()113 public Vector3f getUp() { 114 return up; 115 } 116 117 /** 118 * <code>setUp</code> sets the ring's up vector. 119 * 120 * @param up 121 * the ring's up vector. 122 */ setUp(Vector3f up)123 public void setUp(Vector3f up) { 124 this.up = up; 125 } 126 127 /** 128 * <code>getInnerRadius</code> returns the ring's inner radius. 129 * 130 * @return the ring's inner radius. 131 */ getInnerRadius()132 public float getInnerRadius() { 133 return innerRadius; 134 } 135 136 /** 137 * <code>setInnerRadius</code> sets the ring's inner radius. 138 * 139 * @param innerRadius 140 * the ring's inner radius. 141 */ setInnerRadius(float innerRadius)142 public void setInnerRadius(float innerRadius) { 143 this.innerRadius = innerRadius; 144 } 145 146 /** 147 * <code>getOuterRadius</code> returns the ring's outer radius. 148 * 149 * @return the ring's outer radius. 150 */ getOuterRadius()151 public float getOuterRadius() { 152 return outerRadius; 153 } 154 155 /** 156 * <code>setOuterRadius</code> sets the ring's outer radius. 157 * 158 * @param outerRadius 159 * the ring's outer radius. 160 */ setOuterRadius(float outerRadius)161 public void setOuterRadius(float outerRadius) { 162 this.outerRadius = outerRadius; 163 } 164 165 /** 166 * 167 * <code>random</code> returns a random point within the ring. 168 * 169 * @return a random point within the ring. 170 */ random()171 public Vector3f random() { 172 return random(null); 173 } 174 175 /** 176 * 177 * <code>random</code> returns a random point within the ring. 178 * 179 * @param result Vector to store result in 180 * @return a random point within the ring. 181 */ random(Vector3f result)182 public Vector3f random(Vector3f result) { 183 if (result == null) { 184 result = new Vector3f(); 185 } 186 187 // compute a random radius according to the ring area distribution 188 float inner2 = innerRadius * innerRadius, outer2 = outerRadius 189 * outerRadius, r = FastMath.sqrt(inner2 190 + FastMath.nextRandomFloat() * (outer2 - inner2)), theta = FastMath 191 .nextRandomFloat() 192 * FastMath.TWO_PI; 193 up.cross(Vector3f.UNIT_X, b1); 194 if (b1.lengthSquared() < FastMath.FLT_EPSILON) { 195 up.cross(Vector3f.UNIT_Y, b1); 196 } 197 b1.normalizeLocal(); 198 up.cross(b1, b2); 199 result.set(b1).multLocal(r * FastMath.cos(theta)).addLocal(center); 200 result.scaleAdd(r * FastMath.sin(theta), b2, result); 201 return result; 202 } 203 write(JmeExporter e)204 public void write(JmeExporter e) throws IOException { 205 OutputCapsule capsule = e.getCapsule(this); 206 capsule.write(center, "center", Vector3f.ZERO); 207 capsule.write(up, "up", Vector3f.UNIT_Z); 208 capsule.write(innerRadius, "innerRadius", 0f); 209 capsule.write(outerRadius, "outerRadius", 1f); 210 } 211 read(JmeImporter e)212 public void read(JmeImporter e) throws IOException { 213 InputCapsule capsule = e.getCapsule(this); 214 center = (Vector3f) capsule.readSavable("center", 215 Vector3f.ZERO.clone()); 216 up = (Vector3f) capsule 217 .readSavable("up", Vector3f.UNIT_Z.clone()); 218 innerRadius = capsule.readFloat("innerRadius", 0f); 219 outerRadius = capsule.readFloat("outerRadius", 1f); 220 } 221 222 @Override clone()223 public Ring clone() { 224 try { 225 Ring r = (Ring) super.clone(); 226 r.center = center.clone(); 227 r.up = up.clone(); 228 return r; 229 } catch (CloneNotSupportedException e) { 230 throw new AssertionError(); 231 } 232 } 233 }