libgdx 3 D Bullet衝突検出3

42414 ワード

原文の住所:http://blog.xoppa.com/using-the-libgdx-3d-physics-bullet-wrapper-part2/
原文を見ることを勧めます。直接コードを入れます。完全コードの原文にはgithubがあります。
  1 package org.forus.game.test;

  2 

  3 import com.badlogic.gdx.ApplicationListener;

  4 import com.badlogic.gdx.Gdx;

  5 import com.badlogic.gdx.graphics.Color;

  6 import com.badlogic.gdx.graphics.GL20;

  7 import com.badlogic.gdx.graphics.PerspectiveCamera;

  8 import com.badlogic.gdx.graphics.VertexAttributes.Usage;

  9 import com.badlogic.gdx.graphics.g3d.*;

 10 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;

 11 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;

 12 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;

 13 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;

 14 import com.badlogic.gdx.math.MathUtils;

 15 import com.badlogic.gdx.math.Matrix4;

 16 import com.badlogic.gdx.math.Vector3;

 17 import com.badlogic.gdx.physics.bullet.Bullet;

 18 import com.badlogic.gdx.physics.bullet.collision.*;

 19 import com.badlogic.gdx.physics.bullet.dynamics.*;

 20 import com.badlogic.gdx.physics.bullet.linearmath.btMotionState;

 21 import com.badlogic.gdx.utils.Array;

 22 import com.badlogic.gdx.utils.ArrayMap;

 23 import com.badlogic.gdx.utils.Disposable;

 24 

 25 public class CollisionWorldTest2 implements ApplicationListener {

 26     final static short GROUND_FLAG = 1<<8;

 27     final static short OBJECT_FLAG = 1<<9;

 28     final static short ALL_FLAG = -1;

 29 

 30     class MyContactListener extends ContactListener {

 31         /**

 32         @Override

 33         public boolean onContactAdded (int userValue0, int partId0, int index0, int userValue1, int partId1, int index1) {

 34 //            instances.get(userValue0).moving = false;

 35 //            instances.get(userValue1).moving = false;

 36 //            if (userValue0 != 0)

 37 //                ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 38 //            if (userValue1 != 0)

 39 //                ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 40             if (userValue1 == 0)

 41                 ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 42             if (userValue0 == 0)

 43                 ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 44             return true;

 45         }*/

 46 

 47 

 48         //Note that by default the contact callback filter will be set to zero, so overriding this method without setting the contact callback flag and filter values, will cause the callback never to be triggered.

 49         @Override

 50         public boolean onContactAdded (int userValue0, int partId0, int index0, boolean match0,

 51                                        int userValue1, int partId1, int index1, boolean match1) {

 52             if (match0)

 53                 ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 54             if (match1)

 55                 ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);

 56             return true;

 57         }

 58     }

 59 

 60     static class MyMotionState extends btMotionState {

 61         Matrix4 transform;

 62         @Override

 63         public void getWorldTransform (Matrix4 worldTrans) {

 64             worldTrans.set(transform);//TODO          

 65         }

 66         @Override

 67         public void setWorldTransform (Matrix4 worldTrans) {

 68             transform.set(worldTrans);//TODO          

 69         }

 70     }

 71 

 72     static class GameObject extends ModelInstance implements Disposable {

 73         public final btRigidBody body;

 74         public final MyMotionState motionState;

 75 

 76         public GameObject(Model model, String node, btRigidBody.btRigidBodyConstructionInfo constructionInfo) {

 77             super(model, node);

 78             motionState = new MyMotionState();

 79             motionState.transform = transform;

 80             body = new btRigidBody(constructionInfo);

 81             body.setMotionState(motionState);

 82         }

 83 

 84         @Override

 85         public void dispose() {

 86             body.dispose();

 87             motionState.dispose();

 88         }

 89 

 90         static class Constructor implements Disposable {

 91             public final Model model;

 92             public final String node;

 93             public final btCollisionShape shape;

 94             public final btRigidBody.btRigidBodyConstructionInfo constructionInfo;

 95             private static Vector3 localInertia = new Vector3();

 96 

 97             public Constructor(Model model, String node, btCollisionShape shape, float mass) {//mass--the weight of the object,     ,     : , 

 98                 this.model = model;

 99                 this.node = node;

100                 this.shape = shape;

101                 //If the mass is equal or less than zero, we simply set the local inertia also to zero. Otherwise we need to calculate the local intertia

102                 if (mass > 0f)

103                     shape.calculateLocalInertia(mass, localInertia);

104                 else

105                     localInertia.set(0, 0, 0);

106                 this.constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(mass, null, shape, localInertia);

107             }

108 

109             public GameObject construct() {

110                 return new GameObject(model, node, constructionInfo);

111             }

112 

113             @Override

114             public void dispose() {

115                 shape.dispose();

116                 constructionInfo.dispose();

117             }

118         }

119     }

120 

121     PerspectiveCamera cam;

122     CameraInputController camController;

123     ModelBatch modelBatch;

124     Environment environment;

125     Model model;

126     Array<GameObject> instances;

127     ArrayMap<String, GameObject.Constructor> constructors;

128     float spawnTimer;

129 

130     btCollisionConfiguration collisionConfig;

131     btDispatcher dispatcher;

132     MyContactListener contactListener;

133     btBroadphaseInterface broadphase;

134 

135     btDynamicsWorld dynamicsWorld;

136     btConstraintSolver constraintSolver;

137 

138     float angle, speed = 90f;//ground   

139 

140     @Override

141     public void create () {

142         Bullet.init();

143 

144         modelBatch = new ModelBatch();

145         environment = new Environment();

146         environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));

147         environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

148 

149         cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

150         cam.position.set(3f, 7f, 10f);

151         cam.lookAt(0, 4f, 0);

152         cam.near = 1f;

153         cam.far = 300f;

154         cam.update();

155 

156         camController = new CameraInputController(cam);

157         Gdx.input.setInputProcessor(camController);

158 

159         ModelBuilder mb = new ModelBuilder();

160         mb.begin();

161         mb.node().id = "ground";

162         mb.part("ground", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED)))

163                 .box(5f, 1f, 5f);

164         mb.node().id = "sphere";

165         mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.GREEN)))

166                 .sphere(1f, 1f, 1f, 10, 10);

167         mb.node().id = "box";

168         mb.part("box", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.BLUE)))

169                 .box(1f, 1f, 1f);

170         mb.node().id = "cone";

171         mb.part("cone", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.YELLOW)))

172                 .cone(1f, 2f, 1f, 10);

173         mb.node().id = "capsule";

174         mb.part("capsule", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.CYAN)))

175                 .capsule(0.5f, 2f, 10);

176         mb.node().id = "cylinder";

177         mb.part("cylinder", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal,

178                 new Material(ColorAttribute.createDiffuse(Color.MAGENTA))).cylinder(1f, 2f, 1f, 10);

179         model = mb.end();

180 

181         constructors = new ArrayMap<String, GameObject.Constructor>(String.class, GameObject.Constructor.class);

182         constructors.put("ground", new GameObject.Constructor(model, "ground", new btBoxShape(new Vector3(2.5f, 0.5f, 2.5f)), 0f));

183         constructors.put("sphere", new GameObject.Constructor(model, "sphere", new btSphereShape(0.5f), 1f));

184         constructors.put("box", new GameObject.Constructor(model, "box", new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f)), 1f));

185         constructors.put("cone", new GameObject.Constructor(model, "cone", new btConeShape(0.5f, 2f), 1f));

186         constructors.put("capsule", new GameObject.Constructor(model, "capsule", new btCapsuleShape(.5f, 1f), 1f));

187         constructors.put("cylinder", new GameObject.Constructor(model, "cylinder", new btCylinderShape(new Vector3(.5f, 1f, .5f)), 1f));

188 

189         collisionConfig = new btDefaultCollisionConfiguration();

190         dispatcher = new btCollisionDispatcher(collisionConfig);

191         broadphase = new btDbvtBroadphase();

192         constraintSolver = new btSequentialImpulseConstraintSolver();

193         dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);//Discrete  

194         dynamicsWorld.setGravity(new Vector3(0, -10f, 0));

195         contactListener = new MyContactListener();

196 

197         instances = new Array<GameObject>();

198         GameObject object = constructors.get("ground").construct();

199         object.body.setCollisionFlags(object.body.getCollisionFlags()

200                 | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);

201         instances.add(object);

202         //dynamicsWorld.addRigidBody(object.body, GROUND_FLAG, ALL_FLAG);

203         dynamicsWorld.addRigidBody(object.body);

204         object.body.setContactCallbackFlag(GROUND_FLAG);

205         object.body.setContactCallbackFilter(0);//        。  ,       。

206         object.body.setActivationState(Collision.DISABLE_DEACTIVATION);

207     }

208 

209     public void spawn () {

210         GameObject obj = constructors.values[1 + MathUtils.random(constructors.size - 2)].construct();

211         obj.transform.setFromEulerAngles(MathUtils.random(360f), MathUtils.random(360f), MathUtils.random(360f));

212         obj.transform.trn(MathUtils.random(-2.5f, 2.5f), 9f, MathUtils.random(-2.5f, 2.5f));

213         //obj.body.setWorldTransform(obj.transform);

214         obj.body.proceedToTransform(obj.transform);//  motionState 

215         obj.body.setUserValue(instances.size);

216         obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);

217         instances.add(obj);

218         //dynamicsWorld.addRigidBody(obj.body, OBJECT_FLAG, GROUND_FLAG);//   addCollisionObject, makes sure that for example gravity is correctly applied to each object

219         dynamicsWorld.addRigidBody(obj.body);

220         obj.body.setContactCallbackFlag(OBJECT_FLAG);

221         //              !!!    ,        ,           

222         obj.body.setContactCallbackFilter(GROUND_FLAG);// Ground    

223     }

224 

225     @Override

226     public void render () {

227         final float delta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());

228 

229         angle = (angle + delta * speed) % 360f;

230         instances.get(0).transform.setTranslation(0, MathUtils.sinDeg(angle) * 2.5f, 0f);

231         //instances.get(0).body.setWorldTransform(instances.get(0).transform);// motionstate     

232         //instances.get(0).body.activate();//   object.body.setActivationState(Collision.DISABLE_DEACTIVATION);

233 

234 

235         // The discrete dynamics world uses a fixed time step.

236         // This basically means that it will always use the same delta value to perform calculations.

237         // This fixed delta value is supplied as the third argument of stepSimulation.

238         // If the actual delta value (the first argument) is greater than the desired fixed delta value, then the calculation will be done multiple times.

239         // The maximum number of times that this will be done (the maximum number of sub-steps) is specified by the second argument.

240         dynamicsWorld.stepSimulation(delta, 5, 1f/60f);

241         /* motionState ,   

242         for (GameObject obj : instances)

243             obj.body.getWorldTransform(obj.transform);//     body    obj

244 

245         dynamicsWorld.performDiscreteCollisionDetection();

246         */

247 

248         if ((spawnTimer -= delta) < 0) {

249             spawn();

250             spawnTimer = 1.5f;

251         }

252 

253         camController.update();

254 

255         Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1.f);

256         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

257 

258         modelBatch.begin(cam);

259         modelBatch.render(instances, environment);

260         modelBatch.end();

261     }

262 

263     @Override

264     public void dispose () {

265         for (GameObject obj : instances)

266             obj.dispose();

267         instances.clear();

268 

269         for (GameObject.Constructor ctor : constructors.values())

270             ctor.dispose();

271         constructors.clear();

272 

273         dynamicsWorld.dispose();

274         constraintSolver.dispose();

275         broadphase.dispose();

276         dispatcher.dispose();

277         collisionConfig.dispose();

278 

279         contactListener.dispose();

280 

281         modelBatch.dispose();

282         model.dispose();

283     }

284 

285     @Override

286     public void pause () {

287     }

288 

289     @Override

290     public void resume () {

291     }

292 

293     @Override

294     public void resize (int width, int height) {

295     }

296 }