1 /* 2 Copyright (c) 2019-2020 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.ext.newton.shape; 29 30 import dlib.core.ownership; 31 import dlib.core.memory; 32 import dlib.math.vector; 33 import dlib.math.matrix; 34 import dlib.geometry.triangle; 35 import bindbc.newton; 36 import dagon.graphics.mesh; 37 import dagon.graphics.heightmap; 38 import dagon.ext.newton.world; 39 40 abstract class NewtonCollisionShape: Owner 41 { 42 NewtonPhysicsWorld world; 43 NewtonCollision* newtonCollision; 44 45 this(NewtonPhysicsWorld world) 46 { 47 super(world); 48 this.world = world; 49 } 50 51 ~this() 52 { 53 //if (newtonCollision) 54 // NewtonDestroyCollision(newtonCollision); 55 } 56 57 void setTransformation(Matrix4x4f m) 58 { 59 if (newtonCollision) 60 NewtonCollisionSetMatrix(newtonCollision, m.arrayof.ptr); 61 } 62 } 63 64 class NewtonBoxShape: NewtonCollisionShape 65 { 66 Vector3f halfSize; 67 68 this(Vector3f extents, NewtonPhysicsWorld world) 69 { 70 super(world); 71 newtonCollision = NewtonCreateBox(world.newtonWorld, extents.x, extents.y, extents.z, 0, null); 72 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 73 halfSize = extents * 0.5f; 74 } 75 } 76 77 class NewtonSphereShape: NewtonCollisionShape 78 { 79 float radius; 80 81 this(float radius, NewtonPhysicsWorld world) 82 { 83 super(world); 84 this.radius = radius; 85 newtonCollision = NewtonCreateSphere(world.newtonWorld, radius, 0, null); 86 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 87 } 88 } 89 90 class NewtonCylinderShape: NewtonCollisionShape 91 { 92 float radius1; 93 float radius2; 94 float height; 95 96 this(float radius1, float radius2, float height, NewtonPhysicsWorld world) 97 { 98 super(world); 99 this.radius1 = radius1; 100 this.radius2 = radius2; 101 this.height = height; 102 newtonCollision = NewtonCreateCylinder(world.newtonWorld, radius1, radius2, height, 0, null); 103 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 104 } 105 } 106 107 class NewtonChamferCylinderShape: NewtonCollisionShape 108 { 109 float radius; 110 float height; 111 112 this(float radius, float height, NewtonPhysicsWorld world) 113 { 114 super(world); 115 this.radius = radius; 116 this.height = height; 117 newtonCollision = NewtonCreateChamferCylinder(world.newtonWorld, radius, height, 0, null); 118 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 119 } 120 } 121 122 class NewtonCapsuleShape: NewtonCollisionShape 123 { 124 float radius1; 125 float radius2; 126 float height; 127 128 this(float radius, float height, NewtonPhysicsWorld world) 129 { 130 super(world); 131 this.radius1 = radius1; 132 this.radius2 = radius2; 133 this.height = height; 134 newtonCollision = NewtonCreateCapsule(world.newtonWorld, radius1, radius2, height, 0, null); 135 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 136 } 137 } 138 139 class NewtonConeShape: NewtonCollisionShape 140 { 141 float radius; 142 float height; 143 144 this(float radius, float height, NewtonPhysicsWorld world) 145 { 146 super(world); 147 this.radius = radius; 148 this.height = height; 149 newtonCollision = NewtonCreateCone(world.newtonWorld, radius, height, 0, null); 150 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 151 } 152 } 153 154 class NewtonMeshShape: NewtonCollisionShape 155 { 156 this(TriangleSet triangleSet, NewtonPhysicsWorld world) 157 { 158 super(world); 159 NewtonMesh* nmesh = NewtonMeshCreate(world.newtonWorld); 160 NewtonMeshBeginBuild(nmesh); 161 foreach(triangle; triangleSet) 162 foreach(i, p; triangle.v) 163 { 164 Vector3f n = triangle.n[i]; 165 NewtonMeshAddPoint(nmesh, p.x, p.y, p.z); 166 NewtonMeshAddNormal(nmesh, n.x, n.y, n.z); 167 } 168 NewtonMeshEndBuild(nmesh); 169 170 newtonCollision = NewtonCreateTreeCollisionFromMesh(world.newtonWorld, nmesh, 0); 171 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 172 173 NewtonMeshDestroy(nmesh); 174 } 175 } 176 177 class NewtonConvexHullShape: NewtonCollisionShape 178 { 179 this(Mesh mesh, float tolerance, NewtonPhysicsWorld world) 180 { 181 super(world); 182 NewtonMesh* nmesh = NewtonMeshCreate(world.newtonWorld); 183 NewtonMeshBeginBuild(nmesh); 184 foreach(face; mesh.indices) 185 foreach(i; face) 186 { 187 Vector3f p = mesh.vertices[i]; 188 Vector3f n = mesh.normals[i]; 189 NewtonMeshAddPoint(nmesh, p.x, p.y, p.z); 190 NewtonMeshAddNormal(nmesh, n.x, n.y, n.z); 191 } 192 NewtonMeshEndBuild(nmesh); 193 194 newtonCollision = NewtonCreateConvexHullFromMesh(world.newtonWorld, nmesh, tolerance, 0); 195 NewtonCollisionSetUserData(newtonCollision, cast(void*)this); 196 197 NewtonMeshDestroy(nmesh); 198 } 199 } 200 201 class NewtonCompoundShape: NewtonCollisionShape 202 { 203 this(NewtonCollisionShape[] shapes, NewtonPhysicsWorld world) 204 { 205 super(world); 206 newtonCollision = NewtonCreateCompoundCollision(world.newtonWorld, 0); 207 NewtonCompoundCollisionBeginAddRemove(newtonCollision); 208 foreach(shape; shapes) 209 { 210 NewtonCompoundCollisionAddSubCollision(newtonCollision, shape.newtonCollision); 211 } 212 NewtonCompoundCollisionEndAddRemove(newtonCollision); 213 } 214 } 215 216 class NewtonHeightmapShape: NewtonCollisionShape 217 { 218 uint width; 219 uint height; 220 float[] elevationMap; 221 ubyte[] attributeMap; 222 223 this(Heightmap heightmap, uint w, uint h, Vector3f scale, NewtonPhysicsWorld world) 224 { 225 super(world); 226 227 width = w; 228 height = h; 229 230 elevationMap = New!(float[])(width * height); 231 attributeMap = New!(ubyte[])(width * height); 232 233 foreach(x; 0..width) 234 foreach(z; 0..height) 235 { 236 float y = heightmap.getHeight( 237 cast(float)x / cast(float)(width - 1), 238 cast(float)z / cast(float)(height - 1)); 239 elevationMap[z * width + x] = y; 240 attributeMap[z * width + x] = 0; // TODO 241 } 242 243 newtonCollision = NewtonCreateHeightFieldCollision(world.newtonWorld, 244 width, height, 1, 0, elevationMap.ptr, cast(char*)attributeMap.ptr, scale.y, scale.x, scale.z, 0); 245 } 246 247 ~this() 248 { 249 Delete(elevationMap); 250 Delete(attributeMap); 251 } 252 }