1 /* 2 Copyright (c) 2013-2014 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module dmech.geometry; 30 31 import std.math; 32 33 import dlib.math.vector; 34 import dlib.math.matrix; 35 import dlib.math.affine; 36 import dlib.math.utils; 37 import dlib.geometry.aabb; 38 39 enum GeomType 40 { 41 Undefined, 42 Sphere, 43 Box, 44 Cylinder, 45 Cone, 46 Ellipsoid, 47 Triangle 48 } 49 50 abstract class Geometry 51 { 52 GeomType type = GeomType.Undefined; 53 54 this() 55 { 56 } 57 58 Vector3f supportPoint(Vector3f dir) 59 { 60 return Vector3f(0.0f, 0.0f, 0.0f); 61 } 62 63 Matrix3x3f inertiaTensor(float mass) 64 { 65 return Matrix3x3f.identity * mass; 66 } 67 68 AABB boundingBox(Vector3f position) 69 { 70 return AABB(position, Vector3f(1.0f, 1.0f, 1.0f)); 71 } 72 } 73 74 class GeomSphere: Geometry 75 { 76 float radius; 77 78 this(float r) 79 { 80 super(); 81 type = GeomType.Sphere; 82 radius = r; 83 } 84 85 override Vector3f supportPoint(Vector3f dir) 86 { 87 return dir.normalized * radius; 88 } 89 90 override Matrix3x3f inertiaTensor(float mass) 91 { 92 float v = 0.4f * mass * radius * radius; 93 94 return matrixf( 95 v, 0, 0, 96 0, v, 0, 97 0, 0, v 98 ); 99 } 100 101 override AABB boundingBox(Vector3f position) 102 { 103 return AABB(position, Vector3f(radius, radius, radius)); 104 } 105 } 106 107 class GeomBox: Geometry 108 { 109 Vector3f halfSize; 110 float bsphereRadius; 111 112 this(Vector3f hsize) 113 { 114 super(); 115 type = GeomType.Box; 116 halfSize = hsize; 117 bsphereRadius = halfSize.length; 118 } 119 120 override Vector3f supportPoint(Vector3f dir) 121 { 122 Vector3f result; 123 result.x = sign(dir.x) * halfSize.x; 124 result.y = sign(dir.y) * halfSize.y; 125 result.z = sign(dir.z) * halfSize.z; 126 return result; 127 } 128 129 override Matrix3x3f inertiaTensor(float mass) 130 { 131 float x2 = halfSize.x * halfSize.x; 132 float y2 = halfSize.y * halfSize.y; 133 float z2 = halfSize.z * halfSize.z; 134 135 return matrixf( 136 (y2 + z2)/3 * mass, 0, 0, 137 0, (x2 + z2)/3 * mass, 0, 138 0, 0, (x2 + y2)/3 * mass 139 ); 140 } 141 142 override AABB boundingBox(Vector3f position) 143 { 144 return AABB(position, 145 Vector3f(bsphereRadius, bsphereRadius, bsphereRadius)); 146 } 147 } 148 149 class GeomCylinder: Geometry 150 { 151 float height; 152 float radius; 153 154 this(float h, float r) 155 { 156 super(); 157 type = GeomType.Cylinder; 158 height = h; 159 radius = r; 160 } 161 162 override Vector3f supportPoint(Vector3f dir) 163 { 164 Vector3f result; 165 float sigma = sqrt((dir.x * dir.x + dir.z * dir.z)); 166 167 if (sigma > 0.0f) 168 { 169 result.x = dir.x / sigma * radius; 170 result.y = sign(dir.y) * height * 0.5f; 171 result.z = dir.z / sigma * radius; 172 } 173 else 174 { 175 result.x = 0.0f; 176 result.y = sign(dir.y) * height * 0.5f; 177 result.z = 0.0f; 178 } 179 180 return result; 181 } 182 183 override Matrix3x3f inertiaTensor(float mass) 184 { 185 float r2 = radius * radius; 186 float h2 = height * height; 187 188 return matrixf( 189 (3*r2 + h2)/12 * mass, 0, 0, 190 0, (3*r2 + h2)/12 * mass, 0, 191 0, 0, r2/2 * mass 192 ); 193 } 194 195 override AABB boundingBox(Vector3f position) 196 { 197 float rsum = radius + radius; 198 float d = sqrt(rsum * rsum + height * height) * 0.5f; 199 return AABB(position, Vector3f(d, d, d)); 200 } 201 } 202 203 class GeomCone: Geometry 204 { 205 float radius; 206 float height; 207 208 this(float h, float r) 209 { 210 super(); 211 type = GeomType.Cone; 212 height = h; 213 radius = r; 214 } 215 216 override Vector3f supportPoint(Vector3f dir) 217 { 218 float zdist = dir[0] * dir[0] + dir[1] * dir[1]; 219 float len = zdist + dir[2] * dir[2]; 220 zdist = sqrt(zdist); 221 len = sqrt(len); 222 float half_h = height * 0.5; 223 float radius = radius; 224 225 float sin_a = radius / sqrt(radius * radius + 4.0f * half_h * half_h); 226 227 if (dir[2] > len * sin_a) 228 return Vector3f(0.0f, 0.0f, half_h); 229 else if (zdist > 0.0f) 230 { 231 float rad = radius / zdist; 232 return Vector3f(rad * dir[0], rad * dir[1], -half_h); 233 } 234 else 235 return Vector3f(0.0f, 0.0f, -half_h); 236 } 237 238 override Matrix3x3f inertiaTensor(float mass) 239 { 240 float r2 = radius * radius; 241 float h2 = height * height; 242 243 return matrixf( 244 (3.0f/80.0f*h2 + 3.0f/20.0f*r2) * mass, 0, 0, 245 0, (3.0f/80.0f*h2 + 3.0f/20.0f*r2) * mass, 0, 246 0, 0, (3.0f/10.0f*r2) * mass 247 ); 248 } 249 250 override AABB boundingBox(Vector3f position) 251 { 252 float rsum = radius + radius; 253 float d = sqrt(rsum * rsum + height * height) * 0.5f; 254 return AABB(position, Vector3f(d, d, d)); 255 } 256 } 257 258 class GeomEllipsoid: Geometry 259 { 260 Vector3f radii; 261 262 this(Vector3f r) 263 { 264 super(); 265 type = GeomType.Ellipsoid; 266 radii = r; 267 } 268 269 override Vector3f supportPoint(Vector3f dir) 270 { 271 return dir.normalized * radii; 272 } 273 274 override Matrix3x3f inertiaTensor(float mass) 275 { 276 float x2 = radii.x * radii.x; 277 float y2 = radii.y * radii.y; 278 float z2 = radii.z * radii.z; 279 280 return matrixf( 281 (y2 + z2)/5 * mass, 0, 0, 282 0, (x2 + z2)/5 * mass, 0, 283 0, 0, (x2 + y2)/5 * mass 284 ); 285 } 286 287 override AABB boundingBox(Vector3f position) 288 { 289 return AABB(position, radii); 290 } 291 } 292 293 class GeomTriangle: Geometry 294 { 295 Vector3f[3] v; 296 297 this(Vector3f a, Vector3f b, Vector3f c) 298 { 299 super(); 300 type = GeomType.Triangle; 301 v[0] = a; 302 v[1] = b; 303 v[2] = c; 304 } 305 306 override Vector3f supportPoint(Vector3f dir) 307 { 308 float dota = dir.dot(v[0]); 309 float dotb = dir.dot(v[1]); 310 float dotc = dir.dot(v[2]); 311 312 if (dota > dotb) 313 { 314 if (dotc > dota) 315 return v[2]; 316 else 317 return v[0]; 318 } 319 else 320 { 321 if (dotc > dotb) 322 return v[2]; 323 else 324 return v[1]; 325 } 326 } 327 328 // TODO: boundingBox 329 } 330