migrating to the latest JUCE version
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,7 +1,7 @@ | ||||
| apply plugin: 'com.android.application' | ||||
|  | ||||
| android { | ||||
|     compileSdkVersion 29 | ||||
|     compileSdkVersion 30 | ||||
|     externalNativeBuild { | ||||
|         cmake { | ||||
|             path "CMakeLists.txt" | ||||
| @@ -20,7 +20,7 @@ android { | ||||
|     defaultConfig { | ||||
|         applicationId "com.juce.pluginhost" | ||||
|         minSdkVersion    23 | ||||
|         targetSdkVersion 29 | ||||
|         targetSdkVersion 30 | ||||
|         externalNativeBuild { | ||||
|             cmake { | ||||
|                 arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF" | ||||
| @@ -47,7 +47,7 @@ android { | ||||
|     productFlavors { | ||||
|         debug_ { | ||||
|             ndk { | ||||
|                 abiFilters "armeabi-v7a", "x86" | ||||
|                 abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64" | ||||
|             } | ||||
|             externalNativeBuild { | ||||
|                 cmake { | ||||
|   | ||||
| @@ -4,8 +4,9 @@ | ||||
|           package="com.juce.pluginhost"> | ||||
|   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" | ||||
|                     android:xlargeScreens="true"/> | ||||
|   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | ||||
|   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> | ||||
|   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | ||||
|   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> | ||||
|   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> | ||||
|   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> | ||||
|   <uses-permission android:name="android.permission.BLUETOOTH"/> | ||||
| @@ -15,7 +16,8 @@ | ||||
|   <uses-feature android:glEsVersion="0x00030000" android:required="true"/> | ||||
|   <application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | ||||
|     <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | ||||
|               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | ||||
|               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true" | ||||
|               android:exported="true"> | ||||
|       <intent-filter> | ||||
|         <action android:name="android.intent.action.MAIN"/> | ||||
|         <category android:name="android.intent.category.LAUNCHER"/> | ||||
|   | ||||
| @@ -1,72 +1,72 @@ | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2020 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
|  | ||||
| //============================================================================== | ||||
| /* This component scrolls a continuous waveform showing the audio that's | ||||
|    coming into whatever audio inputs this object is connected to. | ||||
| */ | ||||
| class LiveScrollingAudioDisplay  : public AudioVisualiserComponent, | ||||
|                                    public AudioIODeviceCallback | ||||
| { | ||||
| public: | ||||
|     LiveScrollingAudioDisplay()  : AudioVisualiserComponent (1) | ||||
|     { | ||||
|         setSamplesPerBlock (256); | ||||
|         setBufferSize (1024); | ||||
|     } | ||||
|  | ||||
|     //============================================================================== | ||||
|     void audioDeviceAboutToStart (AudioIODevice*) override | ||||
|     { | ||||
|         clear(); | ||||
|     } | ||||
|  | ||||
|     void audioDeviceStopped() override | ||||
|     { | ||||
|         clear(); | ||||
|     } | ||||
|  | ||||
|     void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels, | ||||
|                                 float** outputChannelData, int numOutputChannels, | ||||
|                                 int numberOfSamples) override | ||||
|     { | ||||
|         for (int i = 0; i < numberOfSamples; ++i) | ||||
|         { | ||||
|             float inputSample = 0; | ||||
|  | ||||
|             for (int chan = 0; chan < numInputChannels; ++chan) | ||||
|                 if (const float* inputChannel = inputChannelData[chan]) | ||||
|                     inputSample += inputChannel[i];  // find the sum of all the channels | ||||
|  | ||||
|             inputSample *= 10.0f; // boost the level to make it more easily visible. | ||||
|  | ||||
|             pushSample (&inputSample, 1); | ||||
|         } | ||||
|  | ||||
|         // We need to clear the output buffers before returning, in case they're full of junk.. | ||||
|         for (int j = 0; j < numOutputChannels; ++j) | ||||
|             if (float* outputChannel = outputChannelData[j]) | ||||
|                 zeromem (outputChannel, (size_t) numberOfSamples * sizeof (float)); | ||||
|     } | ||||
|  | ||||
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LiveScrollingAudioDisplay) | ||||
| }; | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2022 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
|  | ||||
| //============================================================================== | ||||
| /* This component scrolls a continuous waveform showing the audio that's | ||||
|    coming into whatever audio inputs this object is connected to. | ||||
| */ | ||||
| class LiveScrollingAudioDisplay  : public AudioVisualiserComponent, | ||||
|                                    public AudioIODeviceCallback | ||||
| { | ||||
| public: | ||||
|     LiveScrollingAudioDisplay()  : AudioVisualiserComponent (1) | ||||
|     { | ||||
|         setSamplesPerBlock (256); | ||||
|         setBufferSize (1024); | ||||
|     } | ||||
|  | ||||
|     //============================================================================== | ||||
|     void audioDeviceAboutToStart (AudioIODevice*) override | ||||
|     { | ||||
|         clear(); | ||||
|     } | ||||
|  | ||||
|     void audioDeviceStopped() override | ||||
|     { | ||||
|         clear(); | ||||
|     } | ||||
|  | ||||
|     void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels, | ||||
|                                 float** outputChannelData, int numOutputChannels, | ||||
|                                 int numberOfSamples) override | ||||
|     { | ||||
|         for (int i = 0; i < numberOfSamples; ++i) | ||||
|         { | ||||
|             float inputSample = 0; | ||||
|  | ||||
|             for (int chan = 0; chan < numInputChannels; ++chan) | ||||
|                 if (const float* inputChannel = inputChannelData[chan]) | ||||
|                     inputSample += inputChannel[i];  // find the sum of all the channels | ||||
|  | ||||
|             inputSample *= 10.0f; // boost the level to make it more easily visible. | ||||
|  | ||||
|             pushSample (&inputSample, 1); | ||||
|         } | ||||
|  | ||||
|         // We need to clear the output buffers before returning, in case they're full of junk.. | ||||
|         for (int j = 0; j < numOutputChannels; ++j) | ||||
|             if (float* outputChannel = outputChannelData[j]) | ||||
|                 zeromem (outputChannel, (size_t) numberOfSamples * sizeof (float)); | ||||
|     } | ||||
|  | ||||
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LiveScrollingAudioDisplay) | ||||
| }; | ||||
|   | ||||
| @@ -1,51 +1,51 @@ | ||||
|  | ||||
| #ifndef AddPair_H | ||||
| #define AddPair_H | ||||
|  | ||||
| class AddPair : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     AddPair() | ||||
|     { | ||||
|         m_world->SetGravity(b2Vec2(0.0f,0.0f)); | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_p.SetZero(); | ||||
|             shape.m_radius = 0.1f; | ||||
|  | ||||
|             float minX = -6.0f; | ||||
|             float maxX = 0.0f; | ||||
|             float minY = 4.0f; | ||||
|             float maxY = 6.0f; | ||||
|  | ||||
|             for (int i = 0; i < 400; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position = b2Vec2(RandomFloat(minX,maxX),RandomFloat(minY,maxY)); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 0.01f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.5f, 1.5f); | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-40.0f,5.0f); | ||||
|             bd.bullet = true; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|             body->SetLinearVelocity(b2Vec2(150.0f, 0.0f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new AddPair; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifndef AddPair_H | ||||
| #define AddPair_H | ||||
|  | ||||
| class AddPair : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     AddPair() | ||||
|     { | ||||
|         m_world->SetGravity(b2Vec2(0.0f,0.0f)); | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_p.SetZero(); | ||||
|             shape.m_radius = 0.1f; | ||||
|  | ||||
|             float minX = -6.0f; | ||||
|             float maxX = 0.0f; | ||||
|             float minY = 4.0f; | ||||
|             float maxY = 6.0f; | ||||
|  | ||||
|             for (int i = 0; i < 400; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position = b2Vec2(RandomFloat(minX,maxX),RandomFloat(minY,maxY)); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 0.01f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.5f, 1.5f); | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-40.0f,5.0f); | ||||
|             bd.bullet = true; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|             body->SetLinearVelocity(b2Vec2(150.0f, 0.0f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new AddPair; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,183 +1,183 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef APPLY_FORCE_H | ||||
| #define APPLY_FORCE_H | ||||
|  | ||||
| class ApplyForce : public Test | ||||
| { | ||||
| public: | ||||
|     ApplyForce() | ||||
|     { | ||||
|         m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | ||||
|  | ||||
|         const float32 k_restitution = 0.4f; | ||||
|  | ||||
|         b2Body* ground; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 20.0f); | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape; | ||||
|             sd.density = 0.0f; | ||||
|             sd.restitution = k_restitution; | ||||
|  | ||||
|             // Left vertical | ||||
|             shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Right vertical | ||||
|             shape.Set(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Top horizontal | ||||
|             shape.Set(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Bottom horizontal | ||||
|             shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Transform xf1; | ||||
|             xf1.q.Set(0.3524f * b2_pi); | ||||
|             xf1.p = xf1.q.GetXAxis(); | ||||
|  | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | ||||
|  | ||||
|             b2PolygonShape poly1; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef sd1; | ||||
|             sd1.shape = &poly1; | ||||
|             sd1.density = 4.0f; | ||||
|  | ||||
|             b2Transform xf2; | ||||
|             xf2.q.Set(-0.3524f * b2_pi); | ||||
|             xf2.p = -xf2.q.GetXAxis(); | ||||
|  | ||||
|             vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | ||||
|  | ||||
|             b2PolygonShape poly2; | ||||
|             poly2.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef sd2; | ||||
|             sd2.shape = &poly2; | ||||
|             sd2.density = 2.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.angularDamping = 5.0f; | ||||
|             bd.linearDamping = 0.1f; | ||||
|  | ||||
|             bd.position.Set(0.0f, 2.0f); | ||||
|             bd.angle = b2_pi; | ||||
|             bd.allowSleep = false; | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&sd1); | ||||
|             m_body->CreateFixture(&sd2); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|  | ||||
|                 bd.position.Set(0.0f, 5.0f + 1.54f * i); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 float32 gravity = 10.0f; | ||||
|                 float32 I = body->GetInertia(); | ||||
|                 float32 mass = body->GetMass(); | ||||
|  | ||||
|                 // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) | ||||
|                 float32 radius = b2Sqrt(2.0f * I / mass); | ||||
|  | ||||
|                 b2FrictionJointDef jd; | ||||
|                 jd.localAnchorA.SetZero(); | ||||
|                 jd.localAnchorB.SetZero(); | ||||
|                 jd.bodyA = ground; | ||||
|                 jd.bodyB = body; | ||||
|                 jd.collideConnected = true; | ||||
|                 jd.maxForce = mass * gravity; | ||||
|                 jd.maxTorque = mass * radius * gravity; | ||||
|  | ||||
|                 m_world->CreateJoint(&jd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'w': | ||||
|             { | ||||
|                 b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -200.0f)); | ||||
|                 b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 2.0f)); | ||||
|                 m_body->ApplyForce(f, p); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'a': | ||||
|             { | ||||
|                 m_body->ApplyTorque(50.0f); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             { | ||||
|                 m_body->ApplyTorque(-50.0f); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ApplyForce; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef APPLY_FORCE_H | ||||
| #define APPLY_FORCE_H | ||||
|  | ||||
| class ApplyForce : public Test | ||||
| { | ||||
| public: | ||||
|     ApplyForce() | ||||
|     { | ||||
|         m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | ||||
|  | ||||
|         const float32 k_restitution = 0.4f; | ||||
|  | ||||
|         b2Body* ground; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 20.0f); | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape; | ||||
|             sd.density = 0.0f; | ||||
|             sd.restitution = k_restitution; | ||||
|  | ||||
|             // Left vertical | ||||
|             shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Right vertical | ||||
|             shape.Set(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Top horizontal | ||||
|             shape.Set(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|  | ||||
|             // Bottom horizontal | ||||
|             shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f)); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Transform xf1; | ||||
|             xf1.q.Set(0.3524f * b2_pi); | ||||
|             xf1.p = xf1.q.GetXAxis(); | ||||
|  | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | ||||
|  | ||||
|             b2PolygonShape poly1; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef sd1; | ||||
|             sd1.shape = &poly1; | ||||
|             sd1.density = 4.0f; | ||||
|  | ||||
|             b2Transform xf2; | ||||
|             xf2.q.Set(-0.3524f * b2_pi); | ||||
|             xf2.p = -xf2.q.GetXAxis(); | ||||
|  | ||||
|             vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | ||||
|  | ||||
|             b2PolygonShape poly2; | ||||
|             poly2.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef sd2; | ||||
|             sd2.shape = &poly2; | ||||
|             sd2.density = 2.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.angularDamping = 5.0f; | ||||
|             bd.linearDamping = 0.1f; | ||||
|  | ||||
|             bd.position.Set(0.0f, 2.0f); | ||||
|             bd.angle = b2_pi; | ||||
|             bd.allowSleep = false; | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&sd1); | ||||
|             m_body->CreateFixture(&sd2); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|  | ||||
|                 bd.position.Set(0.0f, 5.0f + 1.54f * i); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 float32 gravity = 10.0f; | ||||
|                 float32 I = body->GetInertia(); | ||||
|                 float32 mass = body->GetMass(); | ||||
|  | ||||
|                 // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) | ||||
|                 float32 radius = b2Sqrt(2.0f * I / mass); | ||||
|  | ||||
|                 b2FrictionJointDef jd; | ||||
|                 jd.localAnchorA.SetZero(); | ||||
|                 jd.localAnchorB.SetZero(); | ||||
|                 jd.bodyA = ground; | ||||
|                 jd.bodyB = body; | ||||
|                 jd.collideConnected = true; | ||||
|                 jd.maxForce = mass * gravity; | ||||
|                 jd.maxTorque = mass * radius * gravity; | ||||
|  | ||||
|                 m_world->CreateJoint(&jd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'w': | ||||
|             { | ||||
|                 b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -200.0f)); | ||||
|                 b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 2.0f)); | ||||
|                 m_body->ApplyForce(f, p); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'a': | ||||
|             { | ||||
|                 m_body->ApplyTorque(50.0f); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             { | ||||
|                 m_body->ApplyTorque(-50.0f); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ApplyForce; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,159 +1,159 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BODY_TYPES_H | ||||
| #define BODY_TYPES_H | ||||
|  | ||||
| class BodyTypes : public Test | ||||
| { | ||||
| public: | ||||
|     BodyTypes() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|  | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Define attachment | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 3.0f); | ||||
|             m_attachment = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 2.0f); | ||||
|             m_attachment->CreateFixture(&shape, 2.0f); | ||||
|         } | ||||
|  | ||||
|         // Define platform | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-4.0f, 5.0f); | ||||
|             m_platform = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.friction = 0.6f; | ||||
|             fd.density = 2.0f; | ||||
|             m_platform->CreateFixture(&fd); | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|             rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f)); | ||||
|             rjd.maxMotorTorque = 50.0f; | ||||
|             rjd.enableMotor = true; | ||||
|             m_world->CreateJoint(&rjd); | ||||
|  | ||||
|             b2PrismaticJointDef pjd; | ||||
|             pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f)); | ||||
|  | ||||
|             pjd.maxMotorForce = 1000.0f; | ||||
|             pjd.enableMotor = true; | ||||
|             pjd.lowerTranslation = -10.0f; | ||||
|             pjd.upperTranslation = 10.0f; | ||||
|             pjd.enableLimit = true; | ||||
|  | ||||
|             m_world->CreateJoint(&pjd); | ||||
|  | ||||
|             m_speed = 3.0f; | ||||
|         } | ||||
|  | ||||
|         // Create a payload | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 8.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.75f, 0.75f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.friction = 0.6f; | ||||
|             fd.density = 2.0f; | ||||
|  | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'd': | ||||
|             m_platform->SetType(b2_dynamicBody); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_platform->SetType(b2_staticBody); | ||||
|             break; | ||||
|  | ||||
|         case 'k': | ||||
|             m_platform->SetType(b2_kinematicBody); | ||||
|             m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f)); | ||||
|             m_platform->SetAngularVelocity(0.0f); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         // Drive the kinematic body. | ||||
|         if (m_platform->GetType() == b2_kinematicBody) | ||||
|         { | ||||
|             b2Vec2 p = m_platform->GetTransform().p; | ||||
|             b2Vec2 v = m_platform->GetLinearVelocity(); | ||||
|  | ||||
|             if ((p.x < -10.0f && v.x < 0.0f) || | ||||
|                 (p.x > 10.0f && v.x > 0.0f)) | ||||
|             { | ||||
|                 v.x = -v.x; | ||||
|                 m_platform->SetLinearVelocity(v); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new BodyTypes; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_attachment; | ||||
|     b2Body* m_platform; | ||||
|     float32 m_speed; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BODY_TYPES_H | ||||
| #define BODY_TYPES_H | ||||
|  | ||||
| class BodyTypes : public Test | ||||
| { | ||||
| public: | ||||
|     BodyTypes() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|  | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Define attachment | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 3.0f); | ||||
|             m_attachment = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 2.0f); | ||||
|             m_attachment->CreateFixture(&shape, 2.0f); | ||||
|         } | ||||
|  | ||||
|         // Define platform | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-4.0f, 5.0f); | ||||
|             m_platform = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.friction = 0.6f; | ||||
|             fd.density = 2.0f; | ||||
|             m_platform->CreateFixture(&fd); | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|             rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f)); | ||||
|             rjd.maxMotorTorque = 50.0f; | ||||
|             rjd.enableMotor = true; | ||||
|             m_world->CreateJoint(&rjd); | ||||
|  | ||||
|             b2PrismaticJointDef pjd; | ||||
|             pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f)); | ||||
|  | ||||
|             pjd.maxMotorForce = 1000.0f; | ||||
|             pjd.enableMotor = true; | ||||
|             pjd.lowerTranslation = -10.0f; | ||||
|             pjd.upperTranslation = 10.0f; | ||||
|             pjd.enableLimit = true; | ||||
|  | ||||
|             m_world->CreateJoint(&pjd); | ||||
|  | ||||
|             m_speed = 3.0f; | ||||
|         } | ||||
|  | ||||
|         // Create a payload | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 8.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.75f, 0.75f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.friction = 0.6f; | ||||
|             fd.density = 2.0f; | ||||
|  | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'd': | ||||
|             m_platform->SetType(b2_dynamicBody); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_platform->SetType(b2_staticBody); | ||||
|             break; | ||||
|  | ||||
|         case 'k': | ||||
|             m_platform->SetType(b2_kinematicBody); | ||||
|             m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f)); | ||||
|             m_platform->SetAngularVelocity(0.0f); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         // Drive the kinematic body. | ||||
|         if (m_platform->GetType() == b2_kinematicBody) | ||||
|         { | ||||
|             b2Vec2 p = m_platform->GetTransform().p; | ||||
|             b2Vec2 v = m_platform->GetLinearVelocity(); | ||||
|  | ||||
|             if ((p.x < -10.0f && v.x < 0.0f) || | ||||
|                 (p.x > 10.0f && v.x > 0.0f)) | ||||
|             { | ||||
|                 v.x = -v.x; | ||||
|                 m_platform->SetLinearVelocity(v); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new BodyTypes; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_attachment; | ||||
|     b2Body* m_platform; | ||||
|     float32 m_speed; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,155 +1,155 @@ | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BREAKABLE_TEST_H | ||||
| #define BREAKABLE_TEST_H | ||||
|  | ||||
| // This is used to test sensor shapes. | ||||
| class Breakable : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 7 | ||||
|     }; | ||||
|  | ||||
|     Breakable() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Breakable dynamic body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 40.0f); | ||||
|             bd.angle = 0.25f * b2_pi; | ||||
|             m_body1 = m_world->CreateBody(&bd); | ||||
|  | ||||
|             m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f); | ||||
|             m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f); | ||||
|  | ||||
|             m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f); | ||||
|             m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f); | ||||
|         } | ||||
|  | ||||
|         m_break = false; | ||||
|         m_broke = false; | ||||
|     } | ||||
|  | ||||
|     void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) | ||||
|     { | ||||
|         if (m_broke) | ||||
|         { | ||||
|             // The body already broke. | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Should the body break? | ||||
|         int32 count = contact->GetManifold()->pointCount; | ||||
|  | ||||
|         float32 maxImpulse = 0.0f; | ||||
|         for (int32 i = 0; i < count; ++i) | ||||
|         { | ||||
|             maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); | ||||
|         } | ||||
|  | ||||
|         if (maxImpulse > 40.0f) | ||||
|         { | ||||
|             // Flag the body for breaking. | ||||
|             m_break = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Break() | ||||
|     { | ||||
|         // Create two bodies from one. | ||||
|         b2Body* body1 = m_piece1->GetBody(); | ||||
|         b2Vec2 center = body1->GetWorldCenter(); | ||||
|  | ||||
|         body1->DestroyFixture(m_piece2); | ||||
|         m_piece2 = NULL; | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position = body1->GetPosition(); | ||||
|         bd.angle = body1->GetAngle(); | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&bd); | ||||
|         m_piece2 = body2->CreateFixture(&m_shape2, 1.0f); | ||||
|  | ||||
|         // Compute consistent velocities for new bodies based on | ||||
|         // cached velocity. | ||||
|         b2Vec2 center1 = body1->GetWorldCenter(); | ||||
|         b2Vec2 center2 = body2->GetWorldCenter(); | ||||
|  | ||||
|         b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center); | ||||
|         b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center); | ||||
|  | ||||
|         body1->SetAngularVelocity(m_angularVelocity); | ||||
|         body1->SetLinearVelocity(velocity1); | ||||
|  | ||||
|         body2->SetAngularVelocity(m_angularVelocity); | ||||
|         body2->SetLinearVelocity(velocity2); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         if (m_break) | ||||
|         { | ||||
|             Break(); | ||||
|             m_broke = true; | ||||
|             m_break = false; | ||||
|         } | ||||
|  | ||||
|         // Cache velocities to improve movement on breakage. | ||||
|         if (m_broke == false) | ||||
|         { | ||||
|             m_velocity = m_body1->GetLinearVelocity(); | ||||
|             m_angularVelocity = m_body1->GetAngularVelocity(); | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Breakable; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body1; | ||||
|     b2Vec2 m_velocity; | ||||
|     float32 m_angularVelocity; | ||||
|     b2PolygonShape m_shape1; | ||||
|     b2PolygonShape m_shape2; | ||||
|     b2Fixture* m_piece1; | ||||
|     b2Fixture* m_piece2; | ||||
|  | ||||
|     bool m_broke; | ||||
|     bool m_break; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BREAKABLE_TEST_H | ||||
| #define BREAKABLE_TEST_H | ||||
|  | ||||
| // This is used to test sensor shapes. | ||||
| class Breakable : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 7 | ||||
|     }; | ||||
|  | ||||
|     Breakable() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Breakable dynamic body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 40.0f); | ||||
|             bd.angle = 0.25f * b2_pi; | ||||
|             m_body1 = m_world->CreateBody(&bd); | ||||
|  | ||||
|             m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f); | ||||
|             m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f); | ||||
|  | ||||
|             m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f); | ||||
|             m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f); | ||||
|         } | ||||
|  | ||||
|         m_break = false; | ||||
|         m_broke = false; | ||||
|     } | ||||
|  | ||||
|     void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) | ||||
|     { | ||||
|         if (m_broke) | ||||
|         { | ||||
|             // The body already broke. | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Should the body break? | ||||
|         int32 count = contact->GetManifold()->pointCount; | ||||
|  | ||||
|         float32 maxImpulse = 0.0f; | ||||
|         for (int32 i = 0; i < count; ++i) | ||||
|         { | ||||
|             maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); | ||||
|         } | ||||
|  | ||||
|         if (maxImpulse > 40.0f) | ||||
|         { | ||||
|             // Flag the body for breaking. | ||||
|             m_break = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Break() | ||||
|     { | ||||
|         // Create two bodies from one. | ||||
|         b2Body* body1 = m_piece1->GetBody(); | ||||
|         b2Vec2 center = body1->GetWorldCenter(); | ||||
|  | ||||
|         body1->DestroyFixture(m_piece2); | ||||
|         m_piece2 = NULL; | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position = body1->GetPosition(); | ||||
|         bd.angle = body1->GetAngle(); | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&bd); | ||||
|         m_piece2 = body2->CreateFixture(&m_shape2, 1.0f); | ||||
|  | ||||
|         // Compute consistent velocities for new bodies based on | ||||
|         // cached velocity. | ||||
|         b2Vec2 center1 = body1->GetWorldCenter(); | ||||
|         b2Vec2 center2 = body2->GetWorldCenter(); | ||||
|  | ||||
|         b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center); | ||||
|         b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center); | ||||
|  | ||||
|         body1->SetAngularVelocity(m_angularVelocity); | ||||
|         body1->SetLinearVelocity(velocity1); | ||||
|  | ||||
|         body2->SetAngularVelocity(m_angularVelocity); | ||||
|         body2->SetLinearVelocity(velocity2); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         if (m_break) | ||||
|         { | ||||
|             Break(); | ||||
|             m_broke = true; | ||||
|             m_break = false; | ||||
|         } | ||||
|  | ||||
|         // Cache velocities to improve movement on breakage. | ||||
|         if (m_broke == false) | ||||
|         { | ||||
|             m_velocity = m_body1->GetLinearVelocity(); | ||||
|             m_angularVelocity = m_body1->GetAngularVelocity(); | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Breakable; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body1; | ||||
|     b2Vec2 m_velocity; | ||||
|     float32 m_angularVelocity; | ||||
|     b2PolygonShape m_shape1; | ||||
|     b2PolygonShape m_shape2; | ||||
|     b2Fixture* m_piece1; | ||||
|     b2Fixture* m_piece2; | ||||
|  | ||||
|     bool m_broke; | ||||
|     bool m_break; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,125 +1,125 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BRIDGE_H | ||||
| #define BRIDGE_H | ||||
|  | ||||
| class Bridge : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 30 | ||||
|     }; | ||||
|  | ||||
|     Bridge() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 if (i == (e_count >> 1)) | ||||
|                 { | ||||
|                     m_middle = body; | ||||
|                 } | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 anchor(-15.0f + 1.0f * e_count, 5.0f); | ||||
|             jd.Initialize(prevBody, ground, anchor); | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-8.0f + 8.0f * i, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 3; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-6.0f + 6.0f * i, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Bridge; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_middle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BRIDGE_H | ||||
| #define BRIDGE_H | ||||
|  | ||||
| class Bridge : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 30 | ||||
|     }; | ||||
|  | ||||
|     Bridge() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 if (i == (e_count >> 1)) | ||||
|                 { | ||||
|                     m_middle = body; | ||||
|                 } | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 anchor(-15.0f + 1.0f * e_count, 5.0f); | ||||
|             jd.Initialize(prevBody, ground, anchor); | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-8.0f + 8.0f * i, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 3; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-6.0f + 6.0f * i, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Bridge; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_middle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,136 +1,136 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BULLET_TEST_H | ||||
| #define BULLET_TEST_H | ||||
|  | ||||
| class BulletTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     BulletTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|  | ||||
|             edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             body->CreateFixture(&edge, 0.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 4.0f); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(2.0f, 0.1f); | ||||
|  | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&box, 1.0f); | ||||
|  | ||||
|             box.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             //m_x = RandomFloat(-1.0f, 1.0f); | ||||
|             m_x = 0.20352793f; | ||||
|             bd.position.Set(m_x, 10.0f); | ||||
|             bd.bullet = true; | ||||
|  | ||||
|             m_bullet = m_world->CreateBody(&bd); | ||||
|             m_bullet->CreateFixture(&box, 100.0f); | ||||
|  | ||||
|             m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Launch() | ||||
|     { | ||||
|         m_body->SetTransform(b2Vec2(0.0f, 4.0f), 0.0f); | ||||
|         m_body->SetLinearVelocity(b2Vec2_zero); | ||||
|         m_body->SetAngularVelocity(0.0f); | ||||
|  | ||||
|         m_x = RandomFloat(-1.0f, 1.0f); | ||||
|         m_bullet->SetTransform(b2Vec2(m_x, 10.0f), 0.0f); | ||||
|         m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|         m_bullet->SetAngularVelocity(0.0f); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|         extern int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         b2_gjkCalls = 0; | ||||
|         b2_gjkIters = 0; | ||||
|         b2_gjkMaxIters = 0; | ||||
|  | ||||
|         b2_toiCalls = 0; | ||||
|         b2_toiIters = 0; | ||||
|         b2_toiMaxIters = 0; | ||||
|         b2_toiRootIters = 0; | ||||
|         b2_toiMaxRootIters = 0; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|         extern int32 b2_toiCalls, b2_toiIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         if (b2_gjkCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | ||||
|                 b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (b2_toiCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | ||||
|                 b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|  | ||||
|             m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | ||||
|                 b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount % 60 == 0) | ||||
|         { | ||||
|             Launch(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new BulletTest; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     b2Body* m_bullet; | ||||
|     float32 m_x; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef BULLET_TEST_H | ||||
| #define BULLET_TEST_H | ||||
|  | ||||
| class BulletTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     BulletTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|  | ||||
|             edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             body->CreateFixture(&edge, 0.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 4.0f); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(2.0f, 0.1f); | ||||
|  | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&box, 1.0f); | ||||
|  | ||||
|             box.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             //m_x = RandomFloat(-1.0f, 1.0f); | ||||
|             m_x = 0.20352793f; | ||||
|             bd.position.Set(m_x, 10.0f); | ||||
|             bd.bullet = true; | ||||
|  | ||||
|             m_bullet = m_world->CreateBody(&bd); | ||||
|             m_bullet->CreateFixture(&box, 100.0f); | ||||
|  | ||||
|             m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Launch() | ||||
|     { | ||||
|         m_body->SetTransform(b2Vec2(0.0f, 4.0f), 0.0f); | ||||
|         m_body->SetLinearVelocity(b2Vec2_zero); | ||||
|         m_body->SetAngularVelocity(0.0f); | ||||
|  | ||||
|         m_x = RandomFloat(-1.0f, 1.0f); | ||||
|         m_bullet->SetTransform(b2Vec2(m_x, 10.0f), 0.0f); | ||||
|         m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|         m_bullet->SetAngularVelocity(0.0f); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|         extern int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         b2_gjkCalls = 0; | ||||
|         b2_gjkIters = 0; | ||||
|         b2_gjkMaxIters = 0; | ||||
|  | ||||
|         b2_toiCalls = 0; | ||||
|         b2_toiIters = 0; | ||||
|         b2_toiMaxIters = 0; | ||||
|         b2_toiRootIters = 0; | ||||
|         b2_toiMaxRootIters = 0; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|         extern int32 b2_toiCalls, b2_toiIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         if (b2_gjkCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | ||||
|                 b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (b2_toiCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | ||||
|                 b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|  | ||||
|             m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | ||||
|                 b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount % 60 == 0) | ||||
|         { | ||||
|             Launch(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new BulletTest; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     b2Body* m_bullet; | ||||
|     float32 m_x; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,211 +1,211 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CANTILEVER_H | ||||
| #define CANTILEVER_H | ||||
|  | ||||
| // It is difficult to make a cantilever made of links completely rigid with weld joints. | ||||
| // You will have to use a high number of iterations to make them stiff. | ||||
| // So why not go ahead and use soft weld joints? They behave like a revolute | ||||
| // joint with a rotational spring. | ||||
| class Cantilever : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 8 | ||||
|     }; | ||||
|  | ||||
|     Cantilever() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|             jd.frequencyHz = 5.0f; | ||||
|             jd.dampingRatio = 0.7f; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < 3; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.0f + 2.0f * i, 15.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 2.0f * i, 15.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-4.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 if (i > 0) | ||||
|                 { | ||||
|                     b2Vec2 anchor(-5.0f + 1.0f * i, 5.0f); | ||||
|                     jd.Initialize(prevBody, body, anchor); | ||||
|                     m_world->CreateJoint(&jd); | ||||
|                 } | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|             jd.frequencyHz = 8.0f; | ||||
|             jd.dampingRatio = 0.7f; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(5.5f + 1.0f * i, 10.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 if (i > 0) | ||||
|                 { | ||||
|                     b2Vec2 anchor(5.0f + 1.0f * i, 10.0f); | ||||
|                     jd.Initialize(prevBody, body, anchor); | ||||
|                     m_world->CreateJoint(&jd); | ||||
|                 } | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-8.0f + 8.0f * i, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-6.0f + 6.0f * i, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Cantilever; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_middle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CANTILEVER_H | ||||
| #define CANTILEVER_H | ||||
|  | ||||
| // It is difficult to make a cantilever made of links completely rigid with weld joints. | ||||
| // You will have to use a high number of iterations to make them stiff. | ||||
| // So why not go ahead and use soft weld joints? They behave like a revolute | ||||
| // joint with a rotational spring. | ||||
| class Cantilever : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 8 | ||||
|     }; | ||||
|  | ||||
|     Cantilever() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|             jd.frequencyHz = 5.0f; | ||||
|             jd.dampingRatio = 0.7f; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < 3; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-14.0f + 2.0f * i, 15.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(-15.0f + 2.0f * i, 15.0f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-4.5f + 1.0f * i, 5.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 if (i > 0) | ||||
|                 { | ||||
|                     b2Vec2 anchor(-5.0f + 1.0f * i, 5.0f); | ||||
|                     jd.Initialize(prevBody, body, anchor); | ||||
|                     m_world->CreateJoint(&jd); | ||||
|                 } | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|  | ||||
|             b2WeldJointDef jd; | ||||
|             jd.frequencyHz = 8.0f; | ||||
|             jd.dampingRatio = 0.7f; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(5.5f + 1.0f * i, 10.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 if (i > 0) | ||||
|                 { | ||||
|                     b2Vec2 anchor(5.0f + 1.0f * i, 10.0f); | ||||
|                     jd.Initialize(prevBody, body, anchor); | ||||
|                     m_world->CreateJoint(&jd); | ||||
|                 } | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 3); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-8.0f + 8.0f * i, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < 2; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-6.0f + 6.0f * i, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Cantilever; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_middle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,286 +1,286 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CAR_H | ||||
| #define CAR_H | ||||
|  | ||||
| // This is a fun demo that shows off the wheel joint | ||||
| class Car : public Test | ||||
| { | ||||
| public: | ||||
|     Car() | ||||
|     { | ||||
|         m_hz = 4.0f; | ||||
|         m_zeta = 0.7f; | ||||
|         m_speed = 50.0f; | ||||
|  | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 0.0f; | ||||
|             fd.friction = 0.6f; | ||||
|  | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             float32 hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f}; | ||||
|  | ||||
|             float32 x = 20.0f, y1 = 0.0f, dx = 5.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 y2 = hs[i]; | ||||
|                 shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | ||||
|                 ground->CreateFixture(&fd); | ||||
|                 y1 = y2; | ||||
|                 x += dx; | ||||
|             } | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 y2 = hs[i]; | ||||
|                 shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | ||||
|                 ground->CreateFixture(&fd); | ||||
|                 y1 = y2; | ||||
|                 x += dx; | ||||
|             } | ||||
|  | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 80.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 40.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 10.0f, 5.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 20.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 40.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x, 20.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Teeter | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(140.0f, 1.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(10.0f, 0.25f); | ||||
|             body->CreateFixture(&box, 1.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.Initialize(ground, body, body->GetPosition()); | ||||
|             jd.lowerAngle = -8.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 8.0f * b2_pi / 180.0f; | ||||
|             jd.enableLimit = true; | ||||
|             m_world->CreateJoint(&jd); | ||||
|  | ||||
|             body->ApplyAngularImpulse(100.0f); | ||||
|         } | ||||
|  | ||||
|         // Bridge | ||||
|         { | ||||
|             int32 N = 20; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.6f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(161.0f + 2.0f * i, -0.125f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(160.0f + 2.0f * i, -0.125f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 anchor(160.0f + 2.0f * N, -0.125f); | ||||
|             jd.Initialize(prevBody, ground, anchor); | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Boxes | ||||
|         { | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2Body* body = NULL; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position.Set(230.0f, 0.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 1.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 2.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 3.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 4.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|         } | ||||
|  | ||||
|         // Car | ||||
|         { | ||||
|             b2PolygonShape chassis; | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(-1.5f, -0.5f); | ||||
|             vertices[1].Set(1.5f, -0.5f); | ||||
|             vertices[2].Set(1.5f, 0.0f); | ||||
|             vertices[3].Set(0.0f, 0.9f); | ||||
|             vertices[4].Set(-1.15f, 0.9f); | ||||
|             vertices[5].Set(-1.5f, 0.2f); | ||||
|             chassis.Set(vertices, 6); | ||||
|  | ||||
|             b2CircleShape circle; | ||||
|             circle.m_radius = 0.4f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 1.0f); | ||||
|             m_car = m_world->CreateBody(&bd); | ||||
|             m_car->CreateFixture(&chassis, 1.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &circle; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.9f; | ||||
|  | ||||
|             bd.position.Set(-1.0f, 0.35f); | ||||
|             m_wheel1 = m_world->CreateBody(&bd); | ||||
|             m_wheel1->CreateFixture(&fd); | ||||
|  | ||||
|             bd.position.Set(1.0f, 0.4f); | ||||
|             m_wheel2 = m_world->CreateBody(&bd); | ||||
|             m_wheel2->CreateFixture(&fd); | ||||
|  | ||||
|             b2WheelJointDef jd; | ||||
|             b2Vec2 axis(0.0f, 1.0f); | ||||
|  | ||||
|             jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis); | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.maxMotorTorque = 20.0f; | ||||
|             jd.enableMotor = true; | ||||
|             jd.frequencyHz = m_hz; | ||||
|             jd.dampingRatio = m_zeta; | ||||
|             m_spring1 = (b2WheelJoint*)m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis); | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.maxMotorTorque = 10.0f; | ||||
|             jd.enableMotor = false; | ||||
|             jd.frequencyHz = m_hz; | ||||
|             jd.dampingRatio = m_zeta; | ||||
|             m_spring2 = (b2WheelJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_spring1->SetMotorSpeed(m_speed); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_spring1->SetMotorSpeed(0.0f); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_spring1->SetMotorSpeed(-m_speed); | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_hz = b2Max(0.0f, m_hz - 1.0f); | ||||
|             m_spring1->SetSpringFrequencyHz(m_hz); | ||||
|             m_spring2->SetSpringFrequencyHz(m_hz); | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_hz += 1.0f; | ||||
|             m_spring1->SetSpringFrequencyHz(m_hz); | ||||
|             m_spring2->SetSpringFrequencyHz(m_hz); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, hz down = q, hz up = e"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "frequency = %g hz, damping ratio = %g", m_hz, m_zeta); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         settings->viewCenter.x = m_car->GetPosition().x; | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Car; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_car; | ||||
|     b2Body* m_wheel1; | ||||
|     b2Body* m_wheel2; | ||||
|  | ||||
|     float32 m_hz; | ||||
|     float32 m_zeta; | ||||
|     float32 m_speed; | ||||
|     b2WheelJoint* m_spring1; | ||||
|     b2WheelJoint* m_spring2; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CAR_H | ||||
| #define CAR_H | ||||
|  | ||||
| // This is a fun demo that shows off the wheel joint | ||||
| class Car : public Test | ||||
| { | ||||
| public: | ||||
|     Car() | ||||
|     { | ||||
|         m_hz = 4.0f; | ||||
|         m_zeta = 0.7f; | ||||
|         m_speed = 50.0f; | ||||
|  | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 0.0f; | ||||
|             fd.friction = 0.6f; | ||||
|  | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             float32 hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f}; | ||||
|  | ||||
|             float32 x = 20.0f, y1 = 0.0f, dx = 5.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 y2 = hs[i]; | ||||
|                 shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | ||||
|                 ground->CreateFixture(&fd); | ||||
|                 y1 = y2; | ||||
|                 x += dx; | ||||
|             } | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 y2 = hs[i]; | ||||
|                 shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | ||||
|                 ground->CreateFixture(&fd); | ||||
|                 y1 = y2; | ||||
|                 x += dx; | ||||
|             } | ||||
|  | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 80.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 40.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 10.0f, 5.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 20.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|  | ||||
|             x += 40.0f; | ||||
|             shape.Set(b2Vec2(x, 0.0f), b2Vec2(x, 20.0f)); | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Teeter | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(140.0f, 1.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(10.0f, 0.25f); | ||||
|             body->CreateFixture(&box, 1.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.Initialize(ground, body, body->GetPosition()); | ||||
|             jd.lowerAngle = -8.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 8.0f * b2_pi / 180.0f; | ||||
|             jd.enableLimit = true; | ||||
|             m_world->CreateJoint(&jd); | ||||
|  | ||||
|             body->ApplyAngularImpulse(100.0f); | ||||
|         } | ||||
|  | ||||
|         // Bridge | ||||
|         { | ||||
|             int32 N = 20; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.6f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(161.0f + 2.0f * i, -0.125f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(160.0f + 2.0f * i, -0.125f); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 anchor(160.0f + 2.0f * N, -0.125f); | ||||
|             jd.Initialize(prevBody, ground, anchor); | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Boxes | ||||
|         { | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2Body* body = NULL; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position.Set(230.0f, 0.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 1.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 2.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 3.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|  | ||||
|             bd.position.Set(230.0f, 4.5f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&box, 0.5f); | ||||
|         } | ||||
|  | ||||
|         // Car | ||||
|         { | ||||
|             b2PolygonShape chassis; | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(-1.5f, -0.5f); | ||||
|             vertices[1].Set(1.5f, -0.5f); | ||||
|             vertices[2].Set(1.5f, 0.0f); | ||||
|             vertices[3].Set(0.0f, 0.9f); | ||||
|             vertices[4].Set(-1.15f, 0.9f); | ||||
|             vertices[5].Set(-1.5f, 0.2f); | ||||
|             chassis.Set(vertices, 6); | ||||
|  | ||||
|             b2CircleShape circle; | ||||
|             circle.m_radius = 0.4f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 1.0f); | ||||
|             m_car = m_world->CreateBody(&bd); | ||||
|             m_car->CreateFixture(&chassis, 1.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &circle; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.9f; | ||||
|  | ||||
|             bd.position.Set(-1.0f, 0.35f); | ||||
|             m_wheel1 = m_world->CreateBody(&bd); | ||||
|             m_wheel1->CreateFixture(&fd); | ||||
|  | ||||
|             bd.position.Set(1.0f, 0.4f); | ||||
|             m_wheel2 = m_world->CreateBody(&bd); | ||||
|             m_wheel2->CreateFixture(&fd); | ||||
|  | ||||
|             b2WheelJointDef jd; | ||||
|             b2Vec2 axis(0.0f, 1.0f); | ||||
|  | ||||
|             jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis); | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.maxMotorTorque = 20.0f; | ||||
|             jd.enableMotor = true; | ||||
|             jd.frequencyHz = m_hz; | ||||
|             jd.dampingRatio = m_zeta; | ||||
|             m_spring1 = (b2WheelJoint*)m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis); | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.maxMotorTorque = 10.0f; | ||||
|             jd.enableMotor = false; | ||||
|             jd.frequencyHz = m_hz; | ||||
|             jd.dampingRatio = m_zeta; | ||||
|             m_spring2 = (b2WheelJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_spring1->SetMotorSpeed(m_speed); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_spring1->SetMotorSpeed(0.0f); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_spring1->SetMotorSpeed(-m_speed); | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_hz = b2Max(0.0f, m_hz - 1.0f); | ||||
|             m_spring1->SetSpringFrequencyHz(m_hz); | ||||
|             m_spring2->SetSpringFrequencyHz(m_hz); | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_hz += 1.0f; | ||||
|             m_spring1->SetSpringFrequencyHz(m_hz); | ||||
|             m_spring2->SetSpringFrequencyHz(m_hz); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, hz down = q, hz up = e"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "frequency = %g hz, damping ratio = %g", m_hz, m_zeta); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         settings->viewCenter.x = m_car->GetPosition().x; | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Car; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_car; | ||||
|     b2Body* m_wheel1; | ||||
|     b2Body* m_wheel2; | ||||
|  | ||||
|     float32 m_hz; | ||||
|     float32 m_zeta; | ||||
|     float32 m_speed; | ||||
|     b2WheelJoint* m_spring1; | ||||
|     b2WheelJoint* m_spring2; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,74 +1,74 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CHAIN_H | ||||
| #define CHAIN_H | ||||
|  | ||||
| class Chain : public Test | ||||
| { | ||||
| public: | ||||
|     Chain() | ||||
|     { | ||||
|         b2Body* ground = {}; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.6f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.collideConnected = false; | ||||
|  | ||||
|             const float32 y = 25.0f; | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int i = 0; i < 30; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.5f + i, y); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(float32(i), y); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Chain; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CHAIN_H | ||||
| #define CHAIN_H | ||||
|  | ||||
| class Chain : public Test | ||||
| { | ||||
| public: | ||||
|     Chain() | ||||
|     { | ||||
|         b2Body* ground = {}; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.6f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.collideConnected = false; | ||||
|  | ||||
|             const float32 y = 25.0f; | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int i = 0; i < 30; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.5f + i, y); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(float32(i), y); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Chain; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,253 +1,253 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CHARACTER_COLLISION_H | ||||
| #define CHARACTER_COLLISION_H | ||||
|  | ||||
| /// This is a test of typical character collision scenarios. This does not | ||||
| /// show how you should implement a character in your application. | ||||
| /// Instead this is used to test smooth collision on edge chains. | ||||
| class CharacterCollision : public Test | ||||
| { | ||||
| public: | ||||
|     CharacterCollision() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Collinear edges with no adjacency information. | ||||
|         // This shows the problematic case where a box shape can hit | ||||
|         // an internal vertex. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-8.0f, 1.0f), b2Vec2(-6.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.Set(b2Vec2(-6.0f, 1.0f), b2Vec2(-4.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.Set(b2Vec2(-4.0f, 1.0f), b2Vec2(-2.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Chain shape | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.angle = 0.25f * b2_pi; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[4]; | ||||
|             vs[0].Set(5.0f, 7.0f); | ||||
|             vs[1].Set(6.0f, 8.0f); | ||||
|             vs[2].Set(7.0f, 8.0f); | ||||
|             vs[3].Set(8.0f, 7.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateChain(vs, 4); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square tiles. This shows that adjacency shapes may | ||||
|         // have non-smooth collision. There is no solution | ||||
|         // to this problem. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(4.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(6.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(8.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square made from an edge loop. Collision should be smooth. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[4]; | ||||
|             vs[0].Set(-1.0f, 3.0f); | ||||
|             vs[1].Set(1.0f, 3.0f); | ||||
|             vs[2].Set(1.0f, 5.0f); | ||||
|             vs[3].Set(-1.0f, 5.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateLoop(vs, 4); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Edge loop. Collision should be smooth. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-10.0f, 4.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[10]; | ||||
|             vs[0].Set(0.0f, 0.0f); | ||||
|             vs[1].Set(6.0f, 0.0f); | ||||
|             vs[2].Set(6.0f, 2.0f); | ||||
|             vs[3].Set(4.0f, 1.0f); | ||||
|             vs[4].Set(2.0f, 2.0f); | ||||
|             vs[5].Set(0.0f, 2.0f); | ||||
|             vs[6].Set(-2.0f, 2.0f); | ||||
|             vs[7].Set(-4.0f, 3.0f); | ||||
|             vs[8].Set(-6.0f, 2.0f); | ||||
|             vs[9].Set(-6.0f, 0.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateLoop(vs, 10); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square character 1 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-3.0f, 8.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Square character 2 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-5.0f, 5.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Hexagon character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-5.0f, 8.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             float32 angle = 0.0f; | ||||
|             float32 delta = b2_pi / 3.0f; | ||||
|             b2Vec2 vertices[6]; | ||||
|             for (int32 i = 0; i < 6; ++i) | ||||
|             { | ||||
|                 vertices[i].Set(0.5f * cosf(angle), 0.5f * sinf(angle)); | ||||
|                 angle += delta; | ||||
|             } | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 6); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(3.0f, 5.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-7.0f, 6.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             m_character = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.25f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 1.0f; | ||||
|             m_character->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         b2Vec2 v = m_character->GetLinearVelocity(); | ||||
|         v.x = -5.0f; | ||||
|         m_character->SetLinearVelocity(v); | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "This tests various character collision shapes."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Limitation: square and hexagon can snag on aligned boxes."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Feature: edge chains have smooth collision inside and out."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CharacterCollision; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_character; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CHARACTER_COLLISION_H | ||||
| #define CHARACTER_COLLISION_H | ||||
|  | ||||
| /// This is a test of typical character collision scenarios. This does not | ||||
| /// show how you should implement a character in your application. | ||||
| /// Instead this is used to test smooth collision on edge chains. | ||||
| class CharacterCollision : public Test | ||||
| { | ||||
| public: | ||||
|     CharacterCollision() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Collinear edges with no adjacency information. | ||||
|         // This shows the problematic case where a box shape can hit | ||||
|         // an internal vertex. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-8.0f, 1.0f), b2Vec2(-6.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.Set(b2Vec2(-6.0f, 1.0f), b2Vec2(-4.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.Set(b2Vec2(-4.0f, 1.0f), b2Vec2(-2.0f, 1.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Chain shape | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.angle = 0.25f * b2_pi; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[4]; | ||||
|             vs[0].Set(5.0f, 7.0f); | ||||
|             vs[1].Set(6.0f, 8.0f); | ||||
|             vs[2].Set(7.0f, 8.0f); | ||||
|             vs[3].Set(8.0f, 7.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateChain(vs, 4); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square tiles. This shows that adjacency shapes may | ||||
|         // have non-smooth collision. There is no solution | ||||
|         // to this problem. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(4.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(6.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|             shape.SetAsBox(1.0f, 1.0f, b2Vec2(8.0f, 3.0f), 0.0f); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square made from an edge loop. Collision should be smooth. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[4]; | ||||
|             vs[0].Set(-1.0f, 3.0f); | ||||
|             vs[1].Set(1.0f, 3.0f); | ||||
|             vs[2].Set(1.0f, 5.0f); | ||||
|             vs[3].Set(-1.0f, 5.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateLoop(vs, 4); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Edge loop. Collision should be smooth. | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-10.0f, 4.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[10]; | ||||
|             vs[0].Set(0.0f, 0.0f); | ||||
|             vs[1].Set(6.0f, 0.0f); | ||||
|             vs[2].Set(6.0f, 2.0f); | ||||
|             vs[3].Set(4.0f, 1.0f); | ||||
|             vs[4].Set(2.0f, 2.0f); | ||||
|             vs[5].Set(0.0f, 2.0f); | ||||
|             vs[6].Set(-2.0f, 2.0f); | ||||
|             vs[7].Set(-4.0f, 3.0f); | ||||
|             vs[8].Set(-6.0f, 2.0f); | ||||
|             vs[9].Set(-6.0f, 0.0f); | ||||
|             b2ChainShape shape; | ||||
|             shape.CreateLoop(vs, 10); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Square character 1 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-3.0f, 8.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Square character 2 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-5.0f, 5.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Hexagon character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-5.0f, 8.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             float32 angle = 0.0f; | ||||
|             float32 delta = b2_pi / 3.0f; | ||||
|             b2Vec2 vertices[6]; | ||||
|             for (int32 i = 0; i < 6; ++i) | ||||
|             { | ||||
|                 vertices[i].Set(0.5f * cosf(angle), 0.5f * sinf(angle)); | ||||
|                 angle += delta; | ||||
|             } | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.Set(vertices, 6); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(3.0f, 5.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.fixedRotation = true; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             body->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-7.0f, 6.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.allowSleep = false; | ||||
|  | ||||
|             m_character = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.25f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 1.0f; | ||||
|             m_character->CreateFixture(&fd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         b2Vec2 v = m_character->GetLinearVelocity(); | ||||
|         v.x = -5.0f; | ||||
|         m_character->SetLinearVelocity(v); | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "This tests various character collision shapes."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Limitation: square and hexagon can snag on aligned boxes."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Feature: edge chains have smooth collision inside and out."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CharacterCollision; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_character; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,176 +1,176 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_FILTERING_H | ||||
| #define COLLISION_FILTERING_H | ||||
|  | ||||
| // This is a test of collision filtering. | ||||
| // There is a triangle, a box, and a circle. | ||||
| // There are 6 shapes. 3 large and 3 small. | ||||
| // The 3 small ones always collide. | ||||
| // The 3 large ones never collide. | ||||
| // The boxes don't collide with triangles (except if both are small). | ||||
| const int16 k_smallGroup = 1; | ||||
| const int16 k_largeGroup = -1; | ||||
|  | ||||
| const uint16 k_defaultCategory = 0x0001; | ||||
| const uint16 k_triangleCategory = 0x0002; | ||||
| const uint16 k_boxCategory = 0x0004; | ||||
| const uint16 k_circleCategory = 0x0008; | ||||
|  | ||||
| const uint16 k_triangleMask = 0xFFFF; | ||||
| const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory; | ||||
| const uint16 k_circleMask = 0xFFFF; | ||||
|  | ||||
| class CollisionFiltering : public Test | ||||
| { | ||||
| public: | ||||
|     CollisionFiltering() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape; | ||||
|             sd.friction = 0.3f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         // Small triangle | ||||
|         b2Vec2 vertices[3]; | ||||
|         vertices[0].Set(-1.0f, 0.0f); | ||||
|         vertices[1].Set(1.0f, 0.0f); | ||||
|         vertices[2].Set(0.0f, 2.0f); | ||||
|         b2PolygonShape polygon; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         b2FixtureDef triangleShapeDef; | ||||
|         triangleShapeDef.shape = &polygon; | ||||
|         triangleShapeDef.density = 1.0f; | ||||
|  | ||||
|         triangleShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         triangleShapeDef.filter.categoryBits = k_triangleCategory; | ||||
|         triangleShapeDef.filter.maskBits = k_triangleMask; | ||||
|  | ||||
|         b2BodyDef triangleBodyDef; | ||||
|         triangleBodyDef.type = b2_dynamicBody; | ||||
|         triangleBodyDef.position.Set(-5.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body1->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Large triangle (recycle definitions) | ||||
|         vertices[0] *= 2.0f; | ||||
|         vertices[1] *= 2.0f; | ||||
|         vertices[2] *= 2.0f; | ||||
|         polygon.Set(vertices, 3); | ||||
|         triangleShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         triangleBodyDef.position.Set(-5.0f, 6.0f); | ||||
|         triangleBodyDef.fixedRotation = true; // look at me! | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body2->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-5.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape p; | ||||
|             p.SetAsBox(0.5f, 1.0f); | ||||
|             body->CreateFixture(&p, 1.0f); | ||||
|  | ||||
|             b2PrismaticJointDef jd; | ||||
|             jd.bodyA = body2; | ||||
|             jd.bodyB = body; | ||||
|             jd.enableLimit = true; | ||||
|             jd.localAnchorA.Set(0.0f, 4.0f); | ||||
|             jd.localAnchorB.SetZero(); | ||||
|             jd.localAxisA.Set(0.0f, 1.0f); | ||||
|             jd.lowerTranslation = -1.0f; | ||||
|             jd.upperTranslation = 1.0f; | ||||
|  | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Small box | ||||
|         polygon.SetAsBox(1.0f, 0.5f); | ||||
|         b2FixtureDef boxShapeDef; | ||||
|         boxShapeDef.shape = &polygon; | ||||
|         boxShapeDef.density = 1.0f; | ||||
|         boxShapeDef.restitution = 0.1f; | ||||
|  | ||||
|         boxShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         boxShapeDef.filter.categoryBits = k_boxCategory; | ||||
|         boxShapeDef.filter.maskBits = k_boxMask; | ||||
|  | ||||
|         b2BodyDef boxBodyDef; | ||||
|         boxBodyDef.type = b2_dynamicBody; | ||||
|         boxBodyDef.position.Set(0.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body3 = m_world->CreateBody(&boxBodyDef); | ||||
|         body3->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Large box (recycle definitions) | ||||
|         polygon.SetAsBox(2.0f, 1.0f); | ||||
|         boxShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         boxBodyDef.position.Set(0.0f, 6.0f); | ||||
|  | ||||
|         b2Body* body4 = m_world->CreateBody(&boxBodyDef); | ||||
|         body4->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Small circle | ||||
|         b2CircleShape circle; | ||||
|         circle.m_radius = 1.0f; | ||||
|  | ||||
|         b2FixtureDef circleShapeDef; | ||||
|         circleShapeDef.shape = &circle; | ||||
|         circleShapeDef.density = 1.0f; | ||||
|  | ||||
|         circleShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         circleShapeDef.filter.categoryBits = k_circleCategory; | ||||
|         circleShapeDef.filter.maskBits = k_circleMask; | ||||
|  | ||||
|         b2BodyDef circleBodyDef; | ||||
|         circleBodyDef.type = b2_dynamicBody; | ||||
|         circleBodyDef.position.Set(5.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body5 = m_world->CreateBody(&circleBodyDef); | ||||
|         body5->CreateFixture(&circleShapeDef); | ||||
|  | ||||
|         // Large circle | ||||
|         circle.m_radius *= 2.0f; | ||||
|         circleShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         circleBodyDef.position.Set(5.0f, 6.0f); | ||||
|  | ||||
|         b2Body* body6 = m_world->CreateBody(&circleBodyDef); | ||||
|         body6->CreateFixture(&circleShapeDef); | ||||
|     } | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CollisionFiltering; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_FILTERING_H | ||||
| #define COLLISION_FILTERING_H | ||||
|  | ||||
| // This is a test of collision filtering. | ||||
| // There is a triangle, a box, and a circle. | ||||
| // There are 6 shapes. 3 large and 3 small. | ||||
| // The 3 small ones always collide. | ||||
| // The 3 large ones never collide. | ||||
| // The boxes don't collide with triangles (except if both are small). | ||||
| const int16 k_smallGroup = 1; | ||||
| const int16 k_largeGroup = -1; | ||||
|  | ||||
| const uint16 k_defaultCategory = 0x0001; | ||||
| const uint16 k_triangleCategory = 0x0002; | ||||
| const uint16 k_boxCategory = 0x0004; | ||||
| const uint16 k_circleCategory = 0x0008; | ||||
|  | ||||
| const uint16 k_triangleMask = 0xFFFF; | ||||
| const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory; | ||||
| const uint16 k_circleMask = 0xFFFF; | ||||
|  | ||||
| class CollisionFiltering : public Test | ||||
| { | ||||
| public: | ||||
|     CollisionFiltering() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape; | ||||
|             sd.friction = 0.3f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         // Small triangle | ||||
|         b2Vec2 vertices[3]; | ||||
|         vertices[0].Set(-1.0f, 0.0f); | ||||
|         vertices[1].Set(1.0f, 0.0f); | ||||
|         vertices[2].Set(0.0f, 2.0f); | ||||
|         b2PolygonShape polygon; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         b2FixtureDef triangleShapeDef; | ||||
|         triangleShapeDef.shape = &polygon; | ||||
|         triangleShapeDef.density = 1.0f; | ||||
|  | ||||
|         triangleShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         triangleShapeDef.filter.categoryBits = k_triangleCategory; | ||||
|         triangleShapeDef.filter.maskBits = k_triangleMask; | ||||
|  | ||||
|         b2BodyDef triangleBodyDef; | ||||
|         triangleBodyDef.type = b2_dynamicBody; | ||||
|         triangleBodyDef.position.Set(-5.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body1->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Large triangle (recycle definitions) | ||||
|         vertices[0] *= 2.0f; | ||||
|         vertices[1] *= 2.0f; | ||||
|         vertices[2] *= 2.0f; | ||||
|         polygon.Set(vertices, 3); | ||||
|         triangleShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         triangleBodyDef.position.Set(-5.0f, 6.0f); | ||||
|         triangleBodyDef.fixedRotation = true; // look at me! | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body2->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-5.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape p; | ||||
|             p.SetAsBox(0.5f, 1.0f); | ||||
|             body->CreateFixture(&p, 1.0f); | ||||
|  | ||||
|             b2PrismaticJointDef jd; | ||||
|             jd.bodyA = body2; | ||||
|             jd.bodyB = body; | ||||
|             jd.enableLimit = true; | ||||
|             jd.localAnchorA.Set(0.0f, 4.0f); | ||||
|             jd.localAnchorB.SetZero(); | ||||
|             jd.localAxisA.Set(0.0f, 1.0f); | ||||
|             jd.lowerTranslation = -1.0f; | ||||
|             jd.upperTranslation = 1.0f; | ||||
|  | ||||
|             m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Small box | ||||
|         polygon.SetAsBox(1.0f, 0.5f); | ||||
|         b2FixtureDef boxShapeDef; | ||||
|         boxShapeDef.shape = &polygon; | ||||
|         boxShapeDef.density = 1.0f; | ||||
|         boxShapeDef.restitution = 0.1f; | ||||
|  | ||||
|         boxShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         boxShapeDef.filter.categoryBits = k_boxCategory; | ||||
|         boxShapeDef.filter.maskBits = k_boxMask; | ||||
|  | ||||
|         b2BodyDef boxBodyDef; | ||||
|         boxBodyDef.type = b2_dynamicBody; | ||||
|         boxBodyDef.position.Set(0.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body3 = m_world->CreateBody(&boxBodyDef); | ||||
|         body3->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Large box (recycle definitions) | ||||
|         polygon.SetAsBox(2.0f, 1.0f); | ||||
|         boxShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         boxBodyDef.position.Set(0.0f, 6.0f); | ||||
|  | ||||
|         b2Body* body4 = m_world->CreateBody(&boxBodyDef); | ||||
|         body4->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Small circle | ||||
|         b2CircleShape circle; | ||||
|         circle.m_radius = 1.0f; | ||||
|  | ||||
|         b2FixtureDef circleShapeDef; | ||||
|         circleShapeDef.shape = &circle; | ||||
|         circleShapeDef.density = 1.0f; | ||||
|  | ||||
|         circleShapeDef.filter.groupIndex = k_smallGroup; | ||||
|         circleShapeDef.filter.categoryBits = k_circleCategory; | ||||
|         circleShapeDef.filter.maskBits = k_circleMask; | ||||
|  | ||||
|         b2BodyDef circleBodyDef; | ||||
|         circleBodyDef.type = b2_dynamicBody; | ||||
|         circleBodyDef.position.Set(5.0f, 2.0f); | ||||
|  | ||||
|         b2Body* body5 = m_world->CreateBody(&circleBodyDef); | ||||
|         body5->CreateFixture(&circleShapeDef); | ||||
|  | ||||
|         // Large circle | ||||
|         circle.m_radius *= 2.0f; | ||||
|         circleShapeDef.filter.groupIndex = k_largeGroup; | ||||
|         circleBodyDef.position.Set(5.0f, 6.0f); | ||||
|  | ||||
|         b2Body* body6 = m_world->CreateBody(&circleBodyDef); | ||||
|         body6->CreateFixture(&circleShapeDef); | ||||
|     } | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CollisionFiltering; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,188 +1,188 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_PROCESSING_H | ||||
| #define COLLISION_PROCESSING_H | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| // This test shows collision processing and tests | ||||
| // deferred body destruction. | ||||
| class CollisionProcessing : public Test | ||||
| { | ||||
| public: | ||||
|     CollisionProcessing() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape;; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         float32 xLo = -5.0f, xHi = 5.0f; | ||||
|         float32 yLo = 2.0f, yHi = 35.0f; | ||||
|  | ||||
|         // Small triangle | ||||
|         b2Vec2 vertices[3]; | ||||
|         vertices[0].Set(-1.0f, 0.0f); | ||||
|         vertices[1].Set(1.0f, 0.0f); | ||||
|         vertices[2].Set(0.0f, 2.0f); | ||||
|  | ||||
|         b2PolygonShape polygon; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         b2FixtureDef triangleShapeDef; | ||||
|         triangleShapeDef.shape = &polygon; | ||||
|         triangleShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef triangleBodyDef; | ||||
|         triangleBodyDef.type = b2_dynamicBody; | ||||
|         triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body1->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Large triangle (recycle definitions) | ||||
|         vertices[0] *= 2.0f; | ||||
|         vertices[1] *= 2.0f; | ||||
|         vertices[2] *= 2.0f; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body2->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Small box | ||||
|         polygon.SetAsBox(1.0f, 0.5f); | ||||
|  | ||||
|         b2FixtureDef boxShapeDef; | ||||
|         boxShapeDef.shape = &polygon; | ||||
|         boxShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef boxBodyDef; | ||||
|         boxBodyDef.type = b2_dynamicBody; | ||||
|         boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body3 = m_world->CreateBody(&boxBodyDef); | ||||
|         body3->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Large box (recycle definitions) | ||||
|         polygon.SetAsBox(2.0f, 1.0f); | ||||
|         boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body4 = m_world->CreateBody(&boxBodyDef); | ||||
|         body4->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Small circle | ||||
|         b2CircleShape circle; | ||||
|         circle.m_radius = 1.0f; | ||||
|  | ||||
|         b2FixtureDef circleShapeDef; | ||||
|         circleShapeDef.shape = &circle; | ||||
|         circleShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef circleBodyDef; | ||||
|         circleBodyDef.type = b2_dynamicBody; | ||||
|         circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body5 = m_world->CreateBody(&circleBodyDef); | ||||
|         body5->CreateFixture(&circleShapeDef); | ||||
|  | ||||
|         // Large circle | ||||
|         circle.m_radius *= 2.0f; | ||||
|         circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body6 = m_world->CreateBody(&circleBodyDef); | ||||
|         body6->CreateFixture(&circleShapeDef); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         // We are going to destroy some bodies according to contact | ||||
|         // points. We must buffer the bodies that should be destroyed | ||||
|         // because they may belong to multiple contact points. | ||||
|         const int32 k_maxNuke = 6; | ||||
|         b2Body* nuke[k_maxNuke]; | ||||
|         int32 nukeCount = 0; | ||||
|  | ||||
|         // Traverse the contact results. Destroy bodies that | ||||
|         // are touching heavier bodies. | ||||
|         for (int32 i = 0; i < m_pointCount; ++i) | ||||
|         { | ||||
|             ContactPoint* point = m_points + i; | ||||
|  | ||||
|             b2Body* body1 = point->fixtureA->GetBody(); | ||||
|             b2Body* body2 = point->fixtureB->GetBody(); | ||||
|             float32 mass1 = body1->GetMass(); | ||||
|             float32 mass2 = body2->GetMass(); | ||||
|  | ||||
|             if (mass1 > 0.0f && mass2 > 0.0f) | ||||
|             { | ||||
|                 if (mass2 > mass1) | ||||
|                 { | ||||
|                     nuke[nukeCount++] = body1; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     nuke[nukeCount++] = body2; | ||||
|                 } | ||||
|  | ||||
|                 if (nukeCount == k_maxNuke) | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Sort the nuke array to group duplicates. | ||||
|         std::sort(nuke, nuke + nukeCount); | ||||
|  | ||||
|         // Destroy the bodies, skipping duplicates. | ||||
|         int32 i = 0; | ||||
|         while (i < nukeCount) | ||||
|         { | ||||
|             b2Body* b = nuke[i++]; | ||||
|             while (i < nukeCount && nuke[i] == b) | ||||
|             { | ||||
|                 ++i; | ||||
|             } | ||||
|  | ||||
|             if (b != m_bomb) | ||||
|             { | ||||
|                 m_world->DestroyBody(b); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CollisionProcessing; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COLLISION_PROCESSING_H | ||||
| #define COLLISION_PROCESSING_H | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| // This test shows collision processing and tests | ||||
| // deferred body destruction. | ||||
| class CollisionProcessing : public Test | ||||
| { | ||||
| public: | ||||
|     CollisionProcessing() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.shape = &shape;; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         float32 xLo = -5.0f, xHi = 5.0f; | ||||
|         float32 yLo = 2.0f, yHi = 35.0f; | ||||
|  | ||||
|         // Small triangle | ||||
|         b2Vec2 vertices[3]; | ||||
|         vertices[0].Set(-1.0f, 0.0f); | ||||
|         vertices[1].Set(1.0f, 0.0f); | ||||
|         vertices[2].Set(0.0f, 2.0f); | ||||
|  | ||||
|         b2PolygonShape polygon; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         b2FixtureDef triangleShapeDef; | ||||
|         triangleShapeDef.shape = &polygon; | ||||
|         triangleShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef triangleBodyDef; | ||||
|         triangleBodyDef.type = b2_dynamicBody; | ||||
|         triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body1->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Large triangle (recycle definitions) | ||||
|         vertices[0] *= 2.0f; | ||||
|         vertices[1] *= 2.0f; | ||||
|         vertices[2] *= 2.0f; | ||||
|         polygon.Set(vertices, 3); | ||||
|  | ||||
|         triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | ||||
|         body2->CreateFixture(&triangleShapeDef); | ||||
|  | ||||
|         // Small box | ||||
|         polygon.SetAsBox(1.0f, 0.5f); | ||||
|  | ||||
|         b2FixtureDef boxShapeDef; | ||||
|         boxShapeDef.shape = &polygon; | ||||
|         boxShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef boxBodyDef; | ||||
|         boxBodyDef.type = b2_dynamicBody; | ||||
|         boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body3 = m_world->CreateBody(&boxBodyDef); | ||||
|         body3->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Large box (recycle definitions) | ||||
|         polygon.SetAsBox(2.0f, 1.0f); | ||||
|         boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body4 = m_world->CreateBody(&boxBodyDef); | ||||
|         body4->CreateFixture(&boxShapeDef); | ||||
|  | ||||
|         // Small circle | ||||
|         b2CircleShape circle; | ||||
|         circle.m_radius = 1.0f; | ||||
|  | ||||
|         b2FixtureDef circleShapeDef; | ||||
|         circleShapeDef.shape = &circle; | ||||
|         circleShapeDef.density = 1.0f; | ||||
|  | ||||
|         b2BodyDef circleBodyDef; | ||||
|         circleBodyDef.type = b2_dynamicBody; | ||||
|         circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body5 = m_world->CreateBody(&circleBodyDef); | ||||
|         body5->CreateFixture(&circleShapeDef); | ||||
|  | ||||
|         // Large circle | ||||
|         circle.m_radius *= 2.0f; | ||||
|         circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | ||||
|  | ||||
|         b2Body* body6 = m_world->CreateBody(&circleBodyDef); | ||||
|         body6->CreateFixture(&circleShapeDef); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         // We are going to destroy some bodies according to contact | ||||
|         // points. We must buffer the bodies that should be destroyed | ||||
|         // because they may belong to multiple contact points. | ||||
|         const int32 k_maxNuke = 6; | ||||
|         b2Body* nuke[k_maxNuke]; | ||||
|         int32 nukeCount = 0; | ||||
|  | ||||
|         // Traverse the contact results. Destroy bodies that | ||||
|         // are touching heavier bodies. | ||||
|         for (int32 i = 0; i < m_pointCount; ++i) | ||||
|         { | ||||
|             ContactPoint* point = m_points + i; | ||||
|  | ||||
|             b2Body* body1 = point->fixtureA->GetBody(); | ||||
|             b2Body* body2 = point->fixtureB->GetBody(); | ||||
|             float32 mass1 = body1->GetMass(); | ||||
|             float32 mass2 = body2->GetMass(); | ||||
|  | ||||
|             if (mass1 > 0.0f && mass2 > 0.0f) | ||||
|             { | ||||
|                 if (mass2 > mass1) | ||||
|                 { | ||||
|                     nuke[nukeCount++] = body1; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     nuke[nukeCount++] = body2; | ||||
|                 } | ||||
|  | ||||
|                 if (nukeCount == k_maxNuke) | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Sort the nuke array to group duplicates. | ||||
|         std::sort(nuke, nuke + nukeCount); | ||||
|  | ||||
|         // Destroy the bodies, skipping duplicates. | ||||
|         int32 i = 0; | ||||
|         while (i < nukeCount) | ||||
|         { | ||||
|             b2Body* b = nuke[i++]; | ||||
|             while (i < nukeCount && nuke[i] == b) | ||||
|             { | ||||
|                 ++i; | ||||
|             } | ||||
|  | ||||
|             if (b != m_bomb) | ||||
|             { | ||||
|                 m_world->DestroyBody(b); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CollisionProcessing; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,143 +1,143 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COMPOUND_SHAPES_H | ||||
| #define COMPOUND_SHAPES_H | ||||
|  | ||||
| // TODO_ERIN test joints on compounds. | ||||
| class CompoundShapes : public Test | ||||
| { | ||||
| public: | ||||
|     CompoundShapes() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | ||||
|  | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 0.5f; | ||||
|             circle1.m_p.Set(-0.5f, 0.5f); | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 0.5f; | ||||
|             circle2.m_p.Set(0.5f, 0.5f); | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x + 5.0f, 1.05f + 2.5f * i); | ||||
|                 bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&circle1, 2.0f); | ||||
|                 body->CreateFixture(&circle2, 0.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape polygon1; | ||||
|             polygon1.SetAsBox(0.25f, 0.5f); | ||||
|  | ||||
|             b2PolygonShape polygon2; | ||||
|             polygon2.SetAsBox(0.25f, 0.5f, b2Vec2(0.0f, -0.5f), 0.5f * b2_pi); | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x - 5.0f, 1.05f + 2.5f * i); | ||||
|                 bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&polygon1, 2.0f); | ||||
|                 body->CreateFixture(&polygon2, 2.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Transform xf1; | ||||
|             xf1.q.Set(0.3524f * b2_pi); | ||||
|             xf1.p = xf1.q.GetXAxis(); | ||||
|  | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             b2PolygonShape triangle1; | ||||
|             vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | ||||
|             triangle1.Set(vertices, 3); | ||||
|  | ||||
|             b2Transform xf2; | ||||
|             xf2.q.Set(-0.3524f * b2_pi); | ||||
|             xf2.p = -xf2.q.GetXAxis(); | ||||
|  | ||||
|             b2PolygonShape triangle2; | ||||
|             vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | ||||
|             triangle2.Set(vertices, 3); | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x, 2.05f + 2.5f * i); | ||||
|                 bd.angle = 0.0f; | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&triangle1, 2.0f); | ||||
|                 body->CreateFixture(&triangle2, 2.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape bottom; | ||||
|             bottom.SetAsBox( 1.5f, 0.15f ); | ||||
|  | ||||
|             b2PolygonShape left; | ||||
|             left.SetAsBox(0.15f, 2.7f, b2Vec2(-1.45f, 2.35f), 0.2f); | ||||
|  | ||||
|             b2PolygonShape right; | ||||
|             right.SetAsBox(0.15f, 2.7f, b2Vec2(1.45f, 2.35f), -0.2f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set( 0.0f, 2.0f ); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&bottom, 4.0f); | ||||
|             body->CreateFixture(&left, 4.0f); | ||||
|             body->CreateFixture(&right, 4.0f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CompoundShapes; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef COMPOUND_SHAPES_H | ||||
| #define COMPOUND_SHAPES_H | ||||
|  | ||||
| // TODO_ERIN test joints on compounds. | ||||
| class CompoundShapes : public Test | ||||
| { | ||||
| public: | ||||
|     CompoundShapes() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | ||||
|  | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 0.5f; | ||||
|             circle1.m_p.Set(-0.5f, 0.5f); | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 0.5f; | ||||
|             circle2.m_p.Set(0.5f, 0.5f); | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x + 5.0f, 1.05f + 2.5f * i); | ||||
|                 bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&circle1, 2.0f); | ||||
|                 body->CreateFixture(&circle2, 0.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape polygon1; | ||||
|             polygon1.SetAsBox(0.25f, 0.5f); | ||||
|  | ||||
|             b2PolygonShape polygon2; | ||||
|             polygon2.SetAsBox(0.25f, 0.5f, b2Vec2(0.0f, -0.5f), 0.5f * b2_pi); | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x - 5.0f, 1.05f + 2.5f * i); | ||||
|                 bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&polygon1, 2.0f); | ||||
|                 body->CreateFixture(&polygon2, 2.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Transform xf1; | ||||
|             xf1.q.Set(0.3524f * b2_pi); | ||||
|             xf1.p = xf1.q.GetXAxis(); | ||||
|  | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             b2PolygonShape triangle1; | ||||
|             vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | ||||
|             triangle1.Set(vertices, 3); | ||||
|  | ||||
|             b2Transform xf2; | ||||
|             xf2.q.Set(-0.3524f * b2_pi); | ||||
|             xf2.p = -xf2.q.GetXAxis(); | ||||
|  | ||||
|             b2PolygonShape triangle2; | ||||
|             vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | ||||
|             vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | ||||
|             vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | ||||
|             triangle2.Set(vertices, 3); | ||||
|  | ||||
|             for (int32 i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 float32 x = RandomFloat(-0.1f, 0.1f); | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(x, 2.05f + 2.5f * i); | ||||
|                 bd.angle = 0.0f; | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&triangle1, 2.0f); | ||||
|                 body->CreateFixture(&triangle2, 2.0f); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape bottom; | ||||
|             bottom.SetAsBox( 1.5f, 0.15f ); | ||||
|  | ||||
|             b2PolygonShape left; | ||||
|             left.SetAsBox(0.15f, 2.7f, b2Vec2(-1.45f, 2.35f), 0.2f); | ||||
|  | ||||
|             b2PolygonShape right; | ||||
|             right.SetAsBox(0.15f, 2.7f, b2Vec2(1.45f, 2.35f), -0.2f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set( 0.0f, 2.0f ); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&bottom, 4.0f); | ||||
|             body->CreateFixture(&left, 4.0f); | ||||
|             body->CreateFixture(&right, 4.0f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new CompoundShapes; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,167 +1,167 @@ | ||||
| /* | ||||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONFINED_H | ||||
| #define CONFINED_H | ||||
|  | ||||
| class Confined : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_columnCount = 0, | ||||
|         e_rowCount = 0 | ||||
|     }; | ||||
|  | ||||
|     Confined() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             // Floor | ||||
|             shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Left wall | ||||
|             shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(-10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Right wall | ||||
|             shape.Set(b2Vec2(10.0f, 0.0f), b2Vec2(10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Roof | ||||
|             shape.Set(b2Vec2(-10.0f, 20.0f), b2Vec2(10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         float32 radius = 0.5f; | ||||
|         b2CircleShape shape; | ||||
|         shape.m_p.SetZero(); | ||||
|         shape.m_radius = radius; | ||||
|  | ||||
|         b2FixtureDef fd; | ||||
|         fd.shape = &shape; | ||||
|         fd.density = 1.0f; | ||||
|         fd.friction = 0.1f; | ||||
|  | ||||
|         for (int32 j = 0; j < e_columnCount; ++j) | ||||
|         { | ||||
|             for (int i = 0; i < e_rowCount; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + (2.1f * j + 1.0f + 0.01f * i) * radius, (2.0f * i + 1.0f) * radius); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | ||||
|     } | ||||
|  | ||||
|     void CreateCircle() | ||||
|     { | ||||
|         float32 radius = 2.0f; | ||||
|         b2CircleShape shape; | ||||
|         shape.m_p.SetZero(); | ||||
|         shape.m_radius = radius; | ||||
|  | ||||
|         b2FixtureDef fd; | ||||
|         fd.shape = &shape; | ||||
|         fd.density = 1.0f; | ||||
|         fd.friction = 0.0f; | ||||
|  | ||||
|         b2Vec2 p(RandomFloat(), 3.0f + RandomFloat()); | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position = p; | ||||
|         //bd.allowSleep = false; | ||||
|         b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|         body->CreateFixture(&fd); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'c': | ||||
|             CreateCircle(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool sleeping = true; | ||||
|         for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | ||||
|         { | ||||
|             if (b->GetType() != b2_dynamicBody) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (b->IsAwake()) | ||||
|             { | ||||
|                 sleeping = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount == 180) | ||||
|         { | ||||
|             m_stepCount += 0; | ||||
|         } | ||||
|  | ||||
|         //if (sleeping) | ||||
|         //{ | ||||
|         //  CreateCircle(); | ||||
|         //} | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | ||||
|         { | ||||
|             if (b->GetType() != b2_dynamicBody) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 p = b->GetPosition(); | ||||
|             if (p.x <= -10.0f || 10.0f <= p.x || p.y <= 0.0f || 20.0f <= p.y) | ||||
|             { | ||||
|                 p.x += 0.0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'c' to create a circle."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Confined; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONFINED_H | ||||
| #define CONFINED_H | ||||
|  | ||||
| class Confined : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_columnCount = 0, | ||||
|         e_rowCount = 0 | ||||
|     }; | ||||
|  | ||||
|     Confined() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             // Floor | ||||
|             shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Left wall | ||||
|             shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(-10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Right wall | ||||
|             shape.Set(b2Vec2(10.0f, 0.0f), b2Vec2(10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             // Roof | ||||
|             shape.Set(b2Vec2(-10.0f, 20.0f), b2Vec2(10.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         float32 radius = 0.5f; | ||||
|         b2CircleShape shape; | ||||
|         shape.m_p.SetZero(); | ||||
|         shape.m_radius = radius; | ||||
|  | ||||
|         b2FixtureDef fd; | ||||
|         fd.shape = &shape; | ||||
|         fd.density = 1.0f; | ||||
|         fd.friction = 0.1f; | ||||
|  | ||||
|         for (int32 j = 0; j < e_columnCount; ++j) | ||||
|         { | ||||
|             for (int i = 0; i < e_rowCount; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + (2.1f * j + 1.0f + 0.01f * i) * radius, (2.0f * i + 1.0f) * radius); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | ||||
|     } | ||||
|  | ||||
|     void CreateCircle() | ||||
|     { | ||||
|         float32 radius = 2.0f; | ||||
|         b2CircleShape shape; | ||||
|         shape.m_p.SetZero(); | ||||
|         shape.m_radius = radius; | ||||
|  | ||||
|         b2FixtureDef fd; | ||||
|         fd.shape = &shape; | ||||
|         fd.density = 1.0f; | ||||
|         fd.friction = 0.0f; | ||||
|  | ||||
|         b2Vec2 p(RandomFloat(), 3.0f + RandomFloat()); | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position = p; | ||||
|         //bd.allowSleep = false; | ||||
|         b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|         body->CreateFixture(&fd); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'c': | ||||
|             CreateCircle(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool sleeping = true; | ||||
|         for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | ||||
|         { | ||||
|             if (b->GetType() != b2_dynamicBody) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (b->IsAwake()) | ||||
|             { | ||||
|                 sleeping = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount == 180) | ||||
|         { | ||||
|             m_stepCount += 0; | ||||
|         } | ||||
|  | ||||
|         //if (sleeping) | ||||
|         //{ | ||||
|         //  CreateCircle(); | ||||
|         //} | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | ||||
|         { | ||||
|             if (b->GetType() != b2_dynamicBody) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2Vec2 p = b->GetPosition(); | ||||
|             if (p.x <= -10.0f || 10.0f <= p.x || p.y <= 0.0f || 20.0f <= p.y) | ||||
|             { | ||||
|                 p.x += 0.0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'c' to create a circle."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Confined; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,137 +1,137 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONTINUOUS_TEST_H | ||||
| #define CONTINUOUS_TEST_H | ||||
|  | ||||
| class ContinuousTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     ContinuousTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|  | ||||
|             edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             body->CreateFixture(&edge, 0.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
| #if 1 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 20.0f); | ||||
|             //bd.angle = 0.1f; | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.0f, 0.1f); | ||||
|  | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             m_angularVelocity = RandomFloat(-50.0f, 50.0f); | ||||
|             //m_angularVelocity = 46.661274f; | ||||
|             m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|             m_body->SetAngularVelocity(m_angularVelocity); | ||||
|         } | ||||
| #else | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 2.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_p.SetZero(); | ||||
|             shape.m_radius = 0.5f; | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             bd.bullet = true; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|             body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     void Launch() | ||||
|     { | ||||
|         m_body->SetTransform(b2Vec2(0.0f, 20.0f), 0.0f); | ||||
|         m_angularVelocity = RandomFloat(-50.0f, 50.0f); | ||||
|         m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|         m_body->SetAngularVelocity(m_angularVelocity); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         if (m_stepCount == 12) | ||||
|         { | ||||
|             m_stepCount += 0; | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|  | ||||
|         if (b2_gjkCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | ||||
|                 b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         extern int32 b2_toiCalls, b2_toiIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         if (b2_toiCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | ||||
|                                 b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|  | ||||
|             m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | ||||
|                 b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount % 60 == 0) | ||||
|         { | ||||
|             //Launch(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ContinuousTest; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     float32 m_angularVelocity; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef CONTINUOUS_TEST_H | ||||
| #define CONTINUOUS_TEST_H | ||||
|  | ||||
| class ContinuousTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     ContinuousTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 0.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|  | ||||
|             edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | ||||
|             body->CreateFixture(&edge, 0.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | ||||
|             body->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
| #if 1 | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 20.0f); | ||||
|             //bd.angle = 0.1f; | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.0f, 0.1f); | ||||
|  | ||||
|             m_body = m_world->CreateBody(&bd); | ||||
|             m_body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             m_angularVelocity = RandomFloat(-50.0f, 50.0f); | ||||
|             //m_angularVelocity = 46.661274f; | ||||
|             m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|             m_body->SetAngularVelocity(m_angularVelocity); | ||||
|         } | ||||
| #else | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 2.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_p.SetZero(); | ||||
|             shape.m_radius = 0.5f; | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             bd.bullet = true; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|             body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     void Launch() | ||||
|     { | ||||
|         m_body->SetTransform(b2Vec2(0.0f, 20.0f), 0.0f); | ||||
|         m_angularVelocity = RandomFloat(-50.0f, 50.0f); | ||||
|         m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | ||||
|         m_body->SetAngularVelocity(m_angularVelocity); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         if (m_stepCount == 12) | ||||
|         { | ||||
|             m_stepCount += 0; | ||||
|         } | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | ||||
|  | ||||
|         if (b2_gjkCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | ||||
|                 b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         extern int32 b2_toiCalls, b2_toiIters; | ||||
|         extern int32 b2_toiRootIters, b2_toiMaxRootIters; | ||||
|  | ||||
|         if (b2_toiCalls > 0) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | ||||
|                                 b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|  | ||||
|             m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | ||||
|                 b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         if (m_stepCount % 60 == 0) | ||||
|         { | ||||
|             //Launch(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ContinuousTest; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     float32 m_angularVelocity; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,135 +1,135 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DISTANCE_TEST_H | ||||
| #define DISTANCE_TEST_H | ||||
|  | ||||
| class DistanceTest : public Test | ||||
| { | ||||
| public: | ||||
|     DistanceTest() | ||||
|     { | ||||
|         { | ||||
|             m_transformA.SetIdentity(); | ||||
|             m_transformA.p.Set(0.0f, -0.2f); | ||||
|             m_polygonA.SetAsBox(10.0f, 0.2f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_positionB.Set(12.017401f, 0.13678508f); | ||||
|             m_angleB = -0.0109265f; | ||||
|             m_transformB.Set(m_positionB, m_angleB); | ||||
|  | ||||
|             m_polygonB.SetAsBox(2.0f, 0.1f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DistanceTest; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         b2DistanceInput input; | ||||
|         input.proxyA.Set(&m_polygonA, 0); | ||||
|         input.proxyB.Set(&m_polygonB, 0); | ||||
|         input.transformA = m_transformA; | ||||
|         input.transformB = m_transformB; | ||||
|         input.useRadii = true; | ||||
|         b2SimplexCache cache; | ||||
|         cache.count = 0; | ||||
|         b2DistanceOutput output; | ||||
|         b2Distance(&output, &cache, &input); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "distance = %g", output.distance); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "iterations = %d", output.iterations); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         { | ||||
|             b2Color color(0.9f, 0.9f, 0.9f); | ||||
|             b2Vec2 v[b2_maxPolygonVertices]; | ||||
|             for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | ||||
|  | ||||
|             for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | ||||
|         } | ||||
|  | ||||
|         b2Vec2 x1 = output.pointA; | ||||
|         b2Vec2 x2 = output.pointB; | ||||
|  | ||||
|         b2Color c1(1.0f, 0.0f, 0.0f); | ||||
|         m_debugDraw.DrawPoint(x1, 4.0f, c1); | ||||
|  | ||||
|         b2Color c2(1.0f, 1.0f, 0.0f); | ||||
|         m_debugDraw.DrawPoint(x2, 4.0f, c2); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_positionB.x -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_positionB.x += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_positionB.y -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'w': | ||||
|             m_positionB.y += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_angleB += 0.1f * b2_pi; | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angleB -= 0.1f * b2_pi; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         m_transformB.Set(m_positionB, m_angleB); | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_positionB; | ||||
|     float32 m_angleB; | ||||
|  | ||||
|     b2Transform m_transformA; | ||||
|     b2Transform m_transformB; | ||||
|     b2PolygonShape m_polygonA; | ||||
|     b2PolygonShape m_polygonB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DISTANCE_TEST_H | ||||
| #define DISTANCE_TEST_H | ||||
|  | ||||
| class DistanceTest : public Test | ||||
| { | ||||
| public: | ||||
|     DistanceTest() | ||||
|     { | ||||
|         { | ||||
|             m_transformA.SetIdentity(); | ||||
|             m_transformA.p.Set(0.0f, -0.2f); | ||||
|             m_polygonA.SetAsBox(10.0f, 0.2f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_positionB.Set(12.017401f, 0.13678508f); | ||||
|             m_angleB = -0.0109265f; | ||||
|             m_transformB.Set(m_positionB, m_angleB); | ||||
|  | ||||
|             m_polygonB.SetAsBox(2.0f, 0.1f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DistanceTest; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         b2DistanceInput input; | ||||
|         input.proxyA.Set(&m_polygonA, 0); | ||||
|         input.proxyB.Set(&m_polygonB, 0); | ||||
|         input.transformA = m_transformA; | ||||
|         input.transformB = m_transformB; | ||||
|         input.useRadii = true; | ||||
|         b2SimplexCache cache; | ||||
|         cache.count = 0; | ||||
|         b2DistanceOutput output; | ||||
|         b2Distance(&output, &cache, &input); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "distance = %g", output.distance); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "iterations = %d", output.iterations); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         { | ||||
|             b2Color color(0.9f, 0.9f, 0.9f); | ||||
|             b2Vec2 v[b2_maxPolygonVertices]; | ||||
|             for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | ||||
|  | ||||
|             for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | ||||
|         } | ||||
|  | ||||
|         b2Vec2 x1 = output.pointA; | ||||
|         b2Vec2 x2 = output.pointB; | ||||
|  | ||||
|         b2Color c1(1.0f, 0.0f, 0.0f); | ||||
|         m_debugDraw.DrawPoint(x1, 4.0f, c1); | ||||
|  | ||||
|         b2Color c2(1.0f, 1.0f, 0.0f); | ||||
|         m_debugDraw.DrawPoint(x2, 4.0f, c2); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_positionB.x -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_positionB.x += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_positionB.y -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'w': | ||||
|             m_positionB.y += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_angleB += 0.1f * b2_pi; | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angleB -= 0.1f * b2_pi; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         m_transformB.Set(m_positionB, m_angleB); | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_positionB; | ||||
|     float32 m_angleB; | ||||
|  | ||||
|     b2Transform m_transformA; | ||||
|     b2Transform m_transformB; | ||||
|     b2PolygonShape m_polygonA; | ||||
|     b2PolygonShape m_polygonB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,215 +1,215 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DOMINOS_H | ||||
| #define DOMINOS_H | ||||
|  | ||||
| class Dominos : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     Dominos() | ||||
|     { | ||||
|         b2Body* b1; | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b1 = m_world->CreateBody(&bd); | ||||
|             b1->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(6.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-1.5f, 10.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.1f, 1.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.1f; | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-6.0f + 1.0f * i, 11.25f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(7.0f, 0.25f, b2Vec2_zero, 0.3f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(1.0f, 6.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2Body* b2; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-7.0f, 4.0f); | ||||
|             b2 = m_world->CreateBody(&bd); | ||||
|             b2->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2Body* b3; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(6.0f, 0.125f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-0.9f, 1.0f); | ||||
|             bd.angle = -0.15f; | ||||
|  | ||||
|             b3 = m_world->CreateBody(&bd); | ||||
|             b3->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         b2RevoluteJointDef jd; | ||||
|         b2Vec2 anchor; | ||||
|  | ||||
|         anchor.Set(-2.0f, 1.0f); | ||||
|         jd.Initialize(b1, b3, anchor); | ||||
|         jd.collideConnected = true; | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b4; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-10.0f, 15.0f); | ||||
|             b4 = m_world->CreateBody(&bd); | ||||
|             b4->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(-7.0f, 15.0f); | ||||
|         jd.Initialize(b2, b4, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b5; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(6.5f, 3.0f); | ||||
|             b5 = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             b2FixtureDef fd; | ||||
|  | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 10.0f; | ||||
|             fd.friction = 0.1f; | ||||
|  | ||||
|             shape.SetAsBox(1.0f, 0.1f, b2Vec2(0.0f, -0.9f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|  | ||||
|             shape.SetAsBox(0.1f, 1.0f, b2Vec2(-0.9f, 0.0f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|  | ||||
|             shape.SetAsBox(0.1f, 1.0f, b2Vec2(0.9f, 0.0f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(6.0f, 2.0f); | ||||
|         jd.Initialize(b1, b5, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b6; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.1f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(6.5f, 4.1f); | ||||
|             b6 = m_world->CreateBody(&bd); | ||||
|             b6->CreateFixture(&shape, 30.0f); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(7.5f, 4.0f); | ||||
|         jd.Initialize(b5, b6, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b7; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.1f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(7.4f, 1.0f); | ||||
|  | ||||
|             b7 = m_world->CreateBody(&bd); | ||||
|             b7->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         b2DistanceJointDef djd; | ||||
|         djd.bodyA = b3; | ||||
|         djd.bodyB = b7; | ||||
|         djd.localAnchorA.Set(6.0f, 0.0f); | ||||
|         djd.localAnchorB.Set(0.0f, -1.0f); | ||||
|         b2Vec2 d = djd.bodyB->GetWorldPoint(djd.localAnchorB) - djd.bodyA->GetWorldPoint(djd.localAnchorA); | ||||
|         djd.length = d.Length(); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         { | ||||
|             float32 radius = 0.2f; | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = radius; | ||||
|  | ||||
|             for (int i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(5.9f + 2.0f * radius * i, 2.4f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 10.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Dominos; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DOMINOS_H | ||||
| #define DOMINOS_H | ||||
|  | ||||
| class Dominos : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     Dominos() | ||||
|     { | ||||
|         b2Body* b1; | ||||
|         { | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             b1 = m_world->CreateBody(&bd); | ||||
|             b1->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(6.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-1.5f, 10.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.1f, 1.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.1f; | ||||
|  | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-6.0f + 1.0f * i, 11.25f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(7.0f, 0.25f, b2Vec2_zero, 0.3f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(1.0f, 6.0f); | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2Body* b2; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-7.0f, 4.0f); | ||||
|             b2 = m_world->CreateBody(&bd); | ||||
|             b2->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2Body* b3; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(6.0f, 0.125f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-0.9f, 1.0f); | ||||
|             bd.angle = -0.15f; | ||||
|  | ||||
|             b3 = m_world->CreateBody(&bd); | ||||
|             b3->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         b2RevoluteJointDef jd; | ||||
|         b2Vec2 anchor; | ||||
|  | ||||
|         anchor.Set(-2.0f, 1.0f); | ||||
|         jd.Initialize(b1, b3, anchor); | ||||
|         jd.collideConnected = true; | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b4; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-10.0f, 15.0f); | ||||
|             b4 = m_world->CreateBody(&bd); | ||||
|             b4->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(-7.0f, 15.0f); | ||||
|         jd.Initialize(b2, b4, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b5; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(6.5f, 3.0f); | ||||
|             b5 = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             b2FixtureDef fd; | ||||
|  | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 10.0f; | ||||
|             fd.friction = 0.1f; | ||||
|  | ||||
|             shape.SetAsBox(1.0f, 0.1f, b2Vec2(0.0f, -0.9f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|  | ||||
|             shape.SetAsBox(0.1f, 1.0f, b2Vec2(-0.9f, 0.0f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|  | ||||
|             shape.SetAsBox(0.1f, 1.0f, b2Vec2(0.9f, 0.0f), 0.0f); | ||||
|             b5->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(6.0f, 2.0f); | ||||
|         jd.Initialize(b1, b5, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b6; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(1.0f, 0.1f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(6.5f, 4.1f); | ||||
|             b6 = m_world->CreateBody(&bd); | ||||
|             b6->CreateFixture(&shape, 30.0f); | ||||
|         } | ||||
|  | ||||
|         anchor.Set(7.5f, 4.0f); | ||||
|         jd.Initialize(b5, b6, anchor); | ||||
|         m_world->CreateJoint(&jd); | ||||
|  | ||||
|         b2Body* b7; | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.1f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(7.4f, 1.0f); | ||||
|  | ||||
|             b7 = m_world->CreateBody(&bd); | ||||
|             b7->CreateFixture(&shape, 10.0f); | ||||
|         } | ||||
|  | ||||
|         b2DistanceJointDef djd; | ||||
|         djd.bodyA = b3; | ||||
|         djd.bodyB = b7; | ||||
|         djd.localAnchorA.Set(6.0f, 0.0f); | ||||
|         djd.localAnchorB.Set(0.0f, -1.0f); | ||||
|         b2Vec2 d = djd.bodyB->GetWorldPoint(djd.localAnchorB) - djd.bodyA->GetWorldPoint(djd.localAnchorA); | ||||
|         djd.length = d.Length(); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         { | ||||
|             float32 radius = 0.2f; | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = radius; | ||||
|  | ||||
|             for (int i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(5.9f + 2.0f * radius * i, 2.4f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 10.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Dominos; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,267 +1,267 @@ | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DUMP_SHELL_H | ||||
| #define DUMP_SHELL_H | ||||
|  | ||||
| // This test holds worlds dumped using b2World::Dump. | ||||
| class DumpShell : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     DumpShell() | ||||
|     { | ||||
|  | ||||
| b2Vec2 g(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
| m_world->SetGravity(g); | ||||
| b2Body** bodies = (b2Body**)b2Alloc(3 * sizeof(b2Body*)); | ||||
| b2Joint** joints = (b2Joint**)b2Alloc(2 * sizeof(b2Joint*)); | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(2); | ||||
|   bd.position.Set(1.304347801208496e+01f, 2.500000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 5.000000000000000e-01f; | ||||
|   bd.angularDamping = 5.000000000000000e-01f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[0] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+00f; | ||||
|     fd.restitution = 5.000000000000000e-01f; | ||||
|     fd.density = 1.000000000000000e+01f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2PolygonShape shape; | ||||
|     b2Vec2 vs[8]; | ||||
|     vs[0].Set(-6.900000095367432e+00f, -3.000000119209290e-01f); | ||||
|     vs[1].Set(2.000000029802322e-01f, -3.000000119209290e-01f); | ||||
|     vs[2].Set(2.000000029802322e-01f, 2.000000029802322e-01f); | ||||
|     vs[3].Set(-6.900000095367432e+00f, 2.000000029802322e-01f); | ||||
|     shape.Set(vs, 4); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[0]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(2); | ||||
|   bd.position.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 5.000000000000000e-01f; | ||||
|   bd.angularDamping = 5.000000000000000e-01f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[1] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+00f; | ||||
|     fd.restitution = 5.000000000000000e-01f; | ||||
|     fd.density = 1.000000000000000e+01f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2PolygonShape shape; | ||||
|     b2Vec2 vs[8]; | ||||
|     vs[0].Set(-3.228000104427338e-01f, -2.957000136375427e-01f); | ||||
|     vs[1].Set(6.885900020599365e+00f, -3.641000092029572e-01f); | ||||
|     vs[2].Set(6.907599925994873e+00f, 3.271999955177307e-01f); | ||||
|     vs[3].Set(-3.228000104427338e-01f, 2.825999855995178e-01f); | ||||
|     shape.Set(vs, 4); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[1]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
|  | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(0); | ||||
|   bd.position.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 0.000000000000000e+00f; | ||||
|   bd.angularDamping = 0.000000000000000e+00f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[2] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
|  | ||||
| { | ||||
|   b2PrismaticJointDef jd; | ||||
|   jd.bodyA = bodies[1]; | ||||
|   jd.bodyB = bodies[0]; | ||||
|   jd.collideConnected = bool(0); | ||||
|   jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   jd.localAnchorB.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | ||||
|   jd.localAxisA.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | ||||
|   jd.referenceAngle = 0.000000000000000e+00f; | ||||
|   jd.enableLimit = bool(1); | ||||
|   jd.lowerTranslation = -2.000000000000000e+01f; | ||||
|   jd.upperTranslation = 0.000000000000000e+00f; | ||||
|   jd.enableMotor = bool(1); | ||||
|   jd.motorSpeed = 0.000000000000000e+00f; | ||||
|   jd.maxMotorForce = 1.000000000000000e+01f; | ||||
|   joints[0] = m_world->CreateJoint(&jd); | ||||
| } | ||||
| { | ||||
|   b2RevoluteJointDef jd; | ||||
|   jd.bodyA = bodies[1]; | ||||
|   jd.bodyB = bodies[2]; | ||||
|   jd.collideConnected = bool(0); | ||||
|   jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   jd.localAnchorB.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | ||||
|   jd.referenceAngle = 0.000000000000000e+00f; | ||||
|   jd.enableLimit = bool(0); | ||||
|   jd.lowerAngle = 0.000000000000000e+00f; | ||||
|   jd.upperAngle = 0.000000000000000e+00f; | ||||
|   jd.enableMotor = bool(0); | ||||
|   jd.motorSpeed = 0.000000000000000e+00f; | ||||
|   jd.maxMotorTorque = 0.000000000000000e+00f; | ||||
|   joints[1] = m_world->CreateJoint(&jd); | ||||
| } | ||||
| b2Free(joints); | ||||
| b2Free(bodies); | ||||
| joints = NULL; | ||||
| bodies = NULL; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DumpShell; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DUMP_SHELL_H | ||||
| #define DUMP_SHELL_H | ||||
|  | ||||
| // This test holds worlds dumped using b2World::Dump. | ||||
| class DumpShell : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     DumpShell() | ||||
|     { | ||||
|  | ||||
| b2Vec2 g(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
| m_world->SetGravity(g); | ||||
| b2Body** bodies = (b2Body**)b2Alloc(3 * sizeof(b2Body*)); | ||||
| b2Joint** joints = (b2Joint**)b2Alloc(2 * sizeof(b2Joint*)); | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(2); | ||||
|   bd.position.Set(1.304347801208496e+01f, 2.500000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 5.000000000000000e-01f; | ||||
|   bd.angularDamping = 5.000000000000000e-01f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[0] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+00f; | ||||
|     fd.restitution = 5.000000000000000e-01f; | ||||
|     fd.density = 1.000000000000000e+01f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2PolygonShape shape; | ||||
|     b2Vec2 vs[8]; | ||||
|     vs[0].Set(-6.900000095367432e+00f, -3.000000119209290e-01f); | ||||
|     vs[1].Set(2.000000029802322e-01f, -3.000000119209290e-01f); | ||||
|     vs[2].Set(2.000000029802322e-01f, 2.000000029802322e-01f); | ||||
|     vs[3].Set(-6.900000095367432e+00f, 2.000000029802322e-01f); | ||||
|     shape.Set(vs, 4); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[0]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(2); | ||||
|   bd.position.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 5.000000000000000e-01f; | ||||
|   bd.angularDamping = 5.000000000000000e-01f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[1] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+00f; | ||||
|     fd.restitution = 5.000000000000000e-01f; | ||||
|     fd.density = 1.000000000000000e+01f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2PolygonShape shape; | ||||
|     b2Vec2 vs[8]; | ||||
|     vs[0].Set(-3.228000104427338e-01f, -2.957000136375427e-01f); | ||||
|     vs[1].Set(6.885900020599365e+00f, -3.641000092029572e-01f); | ||||
|     vs[2].Set(6.907599925994873e+00f, 3.271999955177307e-01f); | ||||
|     vs[3].Set(-3.228000104427338e-01f, 2.825999855995178e-01f); | ||||
|     shape.Set(vs, 4); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[1]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
|  | ||||
| { | ||||
|   b2BodyDef bd; | ||||
|   bd.type = b2BodyType(0); | ||||
|   bd.position.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angle = 0.000000000000000e+00f; | ||||
|   bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   bd.angularVelocity = 0.000000000000000e+00f; | ||||
|   bd.linearDamping = 0.000000000000000e+00f; | ||||
|   bd.angularDamping = 0.000000000000000e+00f; | ||||
|   bd.allowSleep = bool(4); | ||||
|   bd.awake = bool(2); | ||||
|   bd.fixedRotation = bool(0); | ||||
|   bd.bullet = bool(0); | ||||
|   bd.active = bool(32); | ||||
|   bd.gravityScale = 1.000000000000000e+00f; | ||||
|   bodies[2] = m_world->CreateBody(&bd); | ||||
|  | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
|   { | ||||
|     b2FixtureDef fd; | ||||
|     fd.friction = 1.000000000000000e+01f; | ||||
|     fd.restitution = 0.000000000000000e+00f; | ||||
|     fd.density = 0.000000000000000e+00f; | ||||
|     fd.isSensor = bool(0); | ||||
|     fd.filter.categoryBits = uint16(1); | ||||
|     fd.filter.maskBits = uint16(65535); | ||||
|     fd.filter.groupIndex = int16(0); | ||||
|     b2EdgeShape shape; | ||||
|     shape.m_radius = 9.999999776482582e-03f; | ||||
|     shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex1.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | ||||
|     shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|     shape.m_hasVertex0 = bool(0); | ||||
|     shape.m_hasVertex3 = bool(0); | ||||
|  | ||||
|     fd.shape = &shape; | ||||
|  | ||||
|     bodies[2]->CreateFixture(&fd); | ||||
|   } | ||||
| } | ||||
|  | ||||
| { | ||||
|   b2PrismaticJointDef jd; | ||||
|   jd.bodyA = bodies[1]; | ||||
|   jd.bodyB = bodies[0]; | ||||
|   jd.collideConnected = bool(0); | ||||
|   jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   jd.localAnchorB.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | ||||
|   jd.localAxisA.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | ||||
|   jd.referenceAngle = 0.000000000000000e+00f; | ||||
|   jd.enableLimit = bool(1); | ||||
|   jd.lowerTranslation = -2.000000000000000e+01f; | ||||
|   jd.upperTranslation = 0.000000000000000e+00f; | ||||
|   jd.enableMotor = bool(1); | ||||
|   jd.motorSpeed = 0.000000000000000e+00f; | ||||
|   jd.maxMotorForce = 1.000000000000000e+01f; | ||||
|   joints[0] = m_world->CreateJoint(&jd); | ||||
| } | ||||
| { | ||||
|   b2RevoluteJointDef jd; | ||||
|   jd.bodyA = bodies[1]; | ||||
|   jd.bodyB = bodies[2]; | ||||
|   jd.collideConnected = bool(0); | ||||
|   jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | ||||
|   jd.localAnchorB.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | ||||
|   jd.referenceAngle = 0.000000000000000e+00f; | ||||
|   jd.enableLimit = bool(0); | ||||
|   jd.lowerAngle = 0.000000000000000e+00f; | ||||
|   jd.upperAngle = 0.000000000000000e+00f; | ||||
|   jd.enableMotor = bool(0); | ||||
|   jd.motorSpeed = 0.000000000000000e+00f; | ||||
|   jd.maxMotorTorque = 0.000000000000000e+00f; | ||||
|   joints[1] = m_world->CreateJoint(&jd); | ||||
| } | ||||
| b2Free(joints); | ||||
| b2Free(bodies); | ||||
| joints = NULL; | ||||
| bodies = NULL; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DumpShell; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,357 +1,357 @@ | ||||
| /* | ||||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DYNAMIC_TREE_TEST_H | ||||
| #define DYNAMIC_TREE_TEST_H | ||||
|  | ||||
| class DynamicTreeTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_actorCount = 128 | ||||
|     }; | ||||
|  | ||||
|     DynamicTreeTest() | ||||
|     { | ||||
|         m_worldExtent = 15.0f; | ||||
|         m_proxyExtent = 0.5f; | ||||
|  | ||||
|         srand(888); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             Actor* actor = m_actors + i; | ||||
|             GetRandomAABB(&actor->aabb); | ||||
|             actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | ||||
|         } | ||||
|  | ||||
|         m_stepCount = 0; | ||||
|  | ||||
|         float32 h = m_worldExtent; | ||||
|         m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h); | ||||
|         m_queryAABB.upperBound.Set(5.0f, 6.0f + h); | ||||
|  | ||||
|         m_rayCastInput.p1.Set(-5.0, 5.0f + h); | ||||
|         m_rayCastInput.p2.Set(7.0f, -4.0f + h); | ||||
|         //m_rayCastInput.p1.Set(0.0f, 2.0f + h); | ||||
|         //m_rayCastInput.p2.Set(0.0f, -2.0f + h); | ||||
|         m_rayCastInput.maxFraction = 1.0f; | ||||
|  | ||||
|         m_automated = false; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DynamicTreeTest; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         B2_NOT_USED(settings); | ||||
|  | ||||
|         m_rayActor = NULL; | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             m_actors[i].fraction = 1.0f; | ||||
|             m_actors[i].overlap = false; | ||||
|         } | ||||
|  | ||||
|         if (m_automated == true) | ||||
|         { | ||||
|             int32 actionCount = b2Max(1, e_actorCount >> 2); | ||||
|  | ||||
|             for (int32 i = 0; i < actionCount; ++i) | ||||
|             { | ||||
|                 Action(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Query(); | ||||
|         RayCast(); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             Actor* actor = m_actors + i; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|                 continue; | ||||
|  | ||||
|             b2Color c(0.9f, 0.9f, 0.9f); | ||||
|             if (actor == m_rayActor && actor->overlap) | ||||
|             { | ||||
|                 c.Set(0.9f, 0.6f, 0.6f); | ||||
|             } | ||||
|             else if (actor == m_rayActor) | ||||
|             { | ||||
|                 c.Set(0.6f, 0.9f, 0.6f); | ||||
|             } | ||||
|             else if (actor->overlap) | ||||
|             { | ||||
|                 c.Set(0.6f, 0.6f, 0.9f); | ||||
|             } | ||||
|  | ||||
|             m_debugDraw.DrawAABB(&actor->aabb, c); | ||||
|         } | ||||
|  | ||||
|         b2Color c(0.7f, 0.7f, 0.7f); | ||||
|         m_debugDraw.DrawAABB(&m_queryAABB, c); | ||||
|  | ||||
|         m_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c); | ||||
|  | ||||
|         b2Color c1(0.2f, 0.9f, 0.2f); | ||||
|         b2Color c2(0.9f, 0.2f, 0.2f); | ||||
|         m_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1); | ||||
|         m_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2); | ||||
|  | ||||
|         if (m_rayActor) | ||||
|         { | ||||
|             b2Color cr(0.2f, 0.2f, 0.9f); | ||||
|             b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1); | ||||
|             m_debugDraw.DrawPoint(p, 6.0f, cr); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             int32 height = m_tree.GetHeight(); | ||||
|             m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d", height); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         ++m_stepCount; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_automated = !m_automated; | ||||
|             break; | ||||
|  | ||||
|         case 'c': | ||||
|             CreateProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             MoveProxy(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool QueryCallback(int32 proxyId) | ||||
|     { | ||||
|         Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | ||||
|         actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId) | ||||
|     { | ||||
|         Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | ||||
|  | ||||
|         b2RayCastOutput output; | ||||
|         bool hit = actor->aabb.RayCast(&output, input); | ||||
|  | ||||
|         if (hit) | ||||
|         { | ||||
|             m_rayCastOutput = output; | ||||
|             m_rayActor = actor; | ||||
|             m_rayActor->fraction = output.fraction; | ||||
|             return output.fraction; | ||||
|         } | ||||
|  | ||||
|         return input.maxFraction; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     struct Actor | ||||
|     { | ||||
|         b2AABB aabb; | ||||
|         float32 fraction; | ||||
|         bool overlap; | ||||
|         int32 proxyId; | ||||
|     }; | ||||
|  | ||||
|     void GetRandomAABB(b2AABB* aabb) | ||||
|     { | ||||
|         b2Vec2 w; w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent); | ||||
|         //aabb->lowerBound.x = -m_proxyExtent; | ||||
|         //aabb->lowerBound.y = -m_proxyExtent + m_worldExtent; | ||||
|         aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent); | ||||
|         aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent); | ||||
|         aabb->upperBound = aabb->lowerBound + w; | ||||
|     } | ||||
|  | ||||
|     void MoveAABB(b2AABB* aabb) | ||||
|     { | ||||
|         b2Vec2 d; | ||||
|         d.x = RandomFloat(-0.5f, 0.5f); | ||||
|         d.y = RandomFloat(-0.5f, 0.5f); | ||||
|         //d.x = 2.0f; | ||||
|         //d.y = 0.0f; | ||||
|         aabb->lowerBound += d; | ||||
|         aabb->upperBound += d; | ||||
|  | ||||
|         b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound); | ||||
|         b2Vec2 min; min.Set(-m_worldExtent, 0.0f); | ||||
|         b2Vec2 max; max.Set(m_worldExtent, 2.0f * m_worldExtent); | ||||
|         b2Vec2 c = b2Clamp(c0, min, max); | ||||
|  | ||||
|         aabb->lowerBound += c - c0; | ||||
|         aabb->upperBound += c - c0; | ||||
|     } | ||||
|  | ||||
|     void CreateProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|             { | ||||
|                 GetRandomAABB(&actor->aabb); | ||||
|                 actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void DestroyProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId != b2_nullNode) | ||||
|             { | ||||
|                 m_tree.DestroyProxy(actor->proxyId); | ||||
|                 actor->proxyId = b2_nullNode; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void MoveProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2AABB aabb0 = actor->aabb; | ||||
|             MoveAABB(&actor->aabb); | ||||
|             b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter(); | ||||
|             m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Action() | ||||
|     { | ||||
|         int32 choice = rand() % 20; | ||||
|  | ||||
|         switch (choice) | ||||
|         { | ||||
|         case 0: | ||||
|             CreateProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 1: | ||||
|             DestroyProxy(); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             MoveProxy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Query() | ||||
|     { | ||||
|         m_tree.Query(this, m_queryAABB); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             if (m_actors[i].proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb); | ||||
|             B2_NOT_USED(overlap); | ||||
|             b2Assert(overlap == m_actors[i].overlap); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void RayCast() | ||||
|     { | ||||
|         m_rayActor = NULL; | ||||
|  | ||||
|         b2RayCastInput input = m_rayCastInput; | ||||
|  | ||||
|         // Ray cast against the dynamic tree. | ||||
|         m_tree.RayCast(this, input); | ||||
|  | ||||
|         // Brute force ray cast. | ||||
|         Actor* bruteActor = NULL; | ||||
|         b2RayCastOutput bruteOutput; | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             if (m_actors[i].proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2RayCastOutput output; | ||||
|             bool hit = m_actors[i].aabb.RayCast(&output, input); | ||||
|             if (hit) | ||||
|             { | ||||
|                 bruteActor = m_actors + i; | ||||
|                 bruteOutput = output; | ||||
|                 input.maxFraction = output.fraction; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (bruteActor != NULL) | ||||
|         { | ||||
|             b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     float32 m_worldExtent; | ||||
|     float32 m_proxyExtent; | ||||
|  | ||||
|     b2DynamicTree m_tree; | ||||
|     b2AABB m_queryAABB; | ||||
|     b2RayCastInput m_rayCastInput; | ||||
|     b2RayCastOutput m_rayCastOutput; | ||||
|     Actor* m_rayActor; | ||||
|     Actor m_actors[e_actorCount]; | ||||
|     int32 m_stepCount; | ||||
|     bool m_automated; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef DYNAMIC_TREE_TEST_H | ||||
| #define DYNAMIC_TREE_TEST_H | ||||
|  | ||||
| class DynamicTreeTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_actorCount = 128 | ||||
|     }; | ||||
|  | ||||
|     DynamicTreeTest() | ||||
|     { | ||||
|         m_worldExtent = 15.0f; | ||||
|         m_proxyExtent = 0.5f; | ||||
|  | ||||
|         srand(888); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             Actor* actor = m_actors + i; | ||||
|             GetRandomAABB(&actor->aabb); | ||||
|             actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | ||||
|         } | ||||
|  | ||||
|         m_stepCount = 0; | ||||
|  | ||||
|         float32 h = m_worldExtent; | ||||
|         m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h); | ||||
|         m_queryAABB.upperBound.Set(5.0f, 6.0f + h); | ||||
|  | ||||
|         m_rayCastInput.p1.Set(-5.0, 5.0f + h); | ||||
|         m_rayCastInput.p2.Set(7.0f, -4.0f + h); | ||||
|         //m_rayCastInput.p1.Set(0.0f, 2.0f + h); | ||||
|         //m_rayCastInput.p2.Set(0.0f, -2.0f + h); | ||||
|         m_rayCastInput.maxFraction = 1.0f; | ||||
|  | ||||
|         m_automated = false; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new DynamicTreeTest; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         B2_NOT_USED(settings); | ||||
|  | ||||
|         m_rayActor = NULL; | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             m_actors[i].fraction = 1.0f; | ||||
|             m_actors[i].overlap = false; | ||||
|         } | ||||
|  | ||||
|         if (m_automated == true) | ||||
|         { | ||||
|             int32 actionCount = b2Max(1, e_actorCount >> 2); | ||||
|  | ||||
|             for (int32 i = 0; i < actionCount; ++i) | ||||
|             { | ||||
|                 Action(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Query(); | ||||
|         RayCast(); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             Actor* actor = m_actors + i; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|                 continue; | ||||
|  | ||||
|             b2Color c(0.9f, 0.9f, 0.9f); | ||||
|             if (actor == m_rayActor && actor->overlap) | ||||
|             { | ||||
|                 c.Set(0.9f, 0.6f, 0.6f); | ||||
|             } | ||||
|             else if (actor == m_rayActor) | ||||
|             { | ||||
|                 c.Set(0.6f, 0.9f, 0.6f); | ||||
|             } | ||||
|             else if (actor->overlap) | ||||
|             { | ||||
|                 c.Set(0.6f, 0.6f, 0.9f); | ||||
|             } | ||||
|  | ||||
|             m_debugDraw.DrawAABB(&actor->aabb, c); | ||||
|         } | ||||
|  | ||||
|         b2Color c(0.7f, 0.7f, 0.7f); | ||||
|         m_debugDraw.DrawAABB(&m_queryAABB, c); | ||||
|  | ||||
|         m_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c); | ||||
|  | ||||
|         b2Color c1(0.2f, 0.9f, 0.2f); | ||||
|         b2Color c2(0.9f, 0.2f, 0.2f); | ||||
|         m_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1); | ||||
|         m_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2); | ||||
|  | ||||
|         if (m_rayActor) | ||||
|         { | ||||
|             b2Color cr(0.2f, 0.2f, 0.9f); | ||||
|             b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1); | ||||
|             m_debugDraw.DrawPoint(p, 6.0f, cr); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             int32 height = m_tree.GetHeight(); | ||||
|             m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d", height); | ||||
|             m_textLine += 15; | ||||
|         } | ||||
|  | ||||
|         ++m_stepCount; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_automated = !m_automated; | ||||
|             break; | ||||
|  | ||||
|         case 'c': | ||||
|             CreateProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             MoveProxy(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool QueryCallback(int32 proxyId) | ||||
|     { | ||||
|         Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | ||||
|         actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId) | ||||
|     { | ||||
|         Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | ||||
|  | ||||
|         b2RayCastOutput output; | ||||
|         bool hit = actor->aabb.RayCast(&output, input); | ||||
|  | ||||
|         if (hit) | ||||
|         { | ||||
|             m_rayCastOutput = output; | ||||
|             m_rayActor = actor; | ||||
|             m_rayActor->fraction = output.fraction; | ||||
|             return output.fraction; | ||||
|         } | ||||
|  | ||||
|         return input.maxFraction; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     struct Actor | ||||
|     { | ||||
|         b2AABB aabb; | ||||
|         float32 fraction; | ||||
|         bool overlap; | ||||
|         int32 proxyId; | ||||
|     }; | ||||
|  | ||||
|     void GetRandomAABB(b2AABB* aabb) | ||||
|     { | ||||
|         b2Vec2 w; w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent); | ||||
|         //aabb->lowerBound.x = -m_proxyExtent; | ||||
|         //aabb->lowerBound.y = -m_proxyExtent + m_worldExtent; | ||||
|         aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent); | ||||
|         aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent); | ||||
|         aabb->upperBound = aabb->lowerBound + w; | ||||
|     } | ||||
|  | ||||
|     void MoveAABB(b2AABB* aabb) | ||||
|     { | ||||
|         b2Vec2 d; | ||||
|         d.x = RandomFloat(-0.5f, 0.5f); | ||||
|         d.y = RandomFloat(-0.5f, 0.5f); | ||||
|         //d.x = 2.0f; | ||||
|         //d.y = 0.0f; | ||||
|         aabb->lowerBound += d; | ||||
|         aabb->upperBound += d; | ||||
|  | ||||
|         b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound); | ||||
|         b2Vec2 min; min.Set(-m_worldExtent, 0.0f); | ||||
|         b2Vec2 max; max.Set(m_worldExtent, 2.0f * m_worldExtent); | ||||
|         b2Vec2 c = b2Clamp(c0, min, max); | ||||
|  | ||||
|         aabb->lowerBound += c - c0; | ||||
|         aabb->upperBound += c - c0; | ||||
|     } | ||||
|  | ||||
|     void CreateProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|             { | ||||
|                 GetRandomAABB(&actor->aabb); | ||||
|                 actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void DestroyProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId != b2_nullNode) | ||||
|             { | ||||
|                 m_tree.DestroyProxy(actor->proxyId); | ||||
|                 actor->proxyId = b2_nullNode; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void MoveProxy() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             int32 j = rand() % e_actorCount; | ||||
|             Actor* actor = m_actors + j; | ||||
|             if (actor->proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2AABB aabb0 = actor->aabb; | ||||
|             MoveAABB(&actor->aabb); | ||||
|             b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter(); | ||||
|             m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Action() | ||||
|     { | ||||
|         int32 choice = rand() % 20; | ||||
|  | ||||
|         switch (choice) | ||||
|         { | ||||
|         case 0: | ||||
|             CreateProxy(); | ||||
|             break; | ||||
|  | ||||
|         case 1: | ||||
|             DestroyProxy(); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             MoveProxy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Query() | ||||
|     { | ||||
|         m_tree.Query(this, m_queryAABB); | ||||
|  | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             if (m_actors[i].proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb); | ||||
|             B2_NOT_USED(overlap); | ||||
|             b2Assert(overlap == m_actors[i].overlap); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void RayCast() | ||||
|     { | ||||
|         m_rayActor = NULL; | ||||
|  | ||||
|         b2RayCastInput input = m_rayCastInput; | ||||
|  | ||||
|         // Ray cast against the dynamic tree. | ||||
|         m_tree.RayCast(this, input); | ||||
|  | ||||
|         // Brute force ray cast. | ||||
|         Actor* bruteActor = NULL; | ||||
|         b2RayCastOutput bruteOutput; | ||||
|         for (int32 i = 0; i < e_actorCount; ++i) | ||||
|         { | ||||
|             if (m_actors[i].proxyId == b2_nullNode) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2RayCastOutput output; | ||||
|             bool hit = m_actors[i].aabb.RayCast(&output, input); | ||||
|             if (hit) | ||||
|             { | ||||
|                 bruteActor = m_actors + i; | ||||
|                 bruteOutput = output; | ||||
|                 input.maxFraction = output.fraction; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (bruteActor != NULL) | ||||
|         { | ||||
|             b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     float32 m_worldExtent; | ||||
|     float32 m_proxyExtent; | ||||
|  | ||||
|     b2DynamicTree m_tree; | ||||
|     b2AABB m_queryAABB; | ||||
|     b2RayCastInput m_rayCastInput; | ||||
|     b2RayCastOutput m_rayCastOutput; | ||||
|     Actor* m_rayActor; | ||||
|     Actor m_actors[e_actorCount]; | ||||
|     int32 m_stepCount; | ||||
|     bool m_automated; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,249 +1,249 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef EDGE_SHAPES_H | ||||
| #define EDGE_SHAPES_H | ||||
|  | ||||
| class EdgeShapesCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     EdgeShapesCallback() | ||||
|     { | ||||
|         m_fixture = NULL; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         m_fixture = fixture; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|  | ||||
|         return fraction; | ||||
|     } | ||||
|  | ||||
|     b2Fixture* m_fixture; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| class EdgeShapes : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxBodies = 256 | ||||
|     }; | ||||
|  | ||||
|     EdgeShapes() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             float32 x1 = -20.0f; | ||||
|             float32 y1 = 2.0f * cosf(x1 / 10.0f * b2_pi); | ||||
|             for (int32 i = 0; i < 80; ++i) | ||||
|             { | ||||
|                 float32 x2 = x1 + 0.5f; | ||||
|                 float32 y2 = 2.0f * cosf(x2 / 10.0f * b2_pi); | ||||
|  | ||||
|                 b2EdgeShape shape; | ||||
|                 shape.Set(b2Vec2(x1, y1), b2Vec2(x2, y2)); | ||||
|                 ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|                 x1 = x2; | ||||
|                 y1 = y2; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|  | ||||
|         float32 x = RandomFloat(-10.0f, 10.0f); | ||||
|         float32 y = RandomFloat(10.0f, 20.0f); | ||||
|         bd.position.Set(x, y); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|         bd.type = b2_dynamicBody; | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.friction = 0.3f; | ||||
|             fd.density = 20.0f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.friction = 0.3f; | ||||
|             fd.density = 20.0f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool advanceRay = settings->pause == 0 || settings->singleStep; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         float32 L = 25.0f; | ||||
|         b2Vec2 point1(0.0f, 10.0f); | ||||
|         b2Vec2 d(L * cosf(m_angle), -L * b2Abs(sinf(m_angle))); | ||||
|         b2Vec2 point2 = point1 + d; | ||||
|  | ||||
|         EdgeShapesCallback callback; | ||||
|  | ||||
|         m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|         if (callback.m_fixture) | ||||
|         { | ||||
|             m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|  | ||||
|             m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|  | ||||
|             b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|             m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|         } | ||||
|  | ||||
|         if (advanceRay) | ||||
|         { | ||||
|             m_angle += 0.25f * b2_pi / 180.0f; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new EdgeShapes; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[e_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
|  | ||||
|     float32 m_angle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef EDGE_SHAPES_H | ||||
| #define EDGE_SHAPES_H | ||||
|  | ||||
| class EdgeShapesCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     EdgeShapesCallback() | ||||
|     { | ||||
|         m_fixture = NULL; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         m_fixture = fixture; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|  | ||||
|         return fraction; | ||||
|     } | ||||
|  | ||||
|     b2Fixture* m_fixture; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| class EdgeShapes : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxBodies = 256 | ||||
|     }; | ||||
|  | ||||
|     EdgeShapes() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             float32 x1 = -20.0f; | ||||
|             float32 y1 = 2.0f * cosf(x1 / 10.0f * b2_pi); | ||||
|             for (int32 i = 0; i < 80; ++i) | ||||
|             { | ||||
|                 float32 x2 = x1 + 0.5f; | ||||
|                 float32 y2 = 2.0f * cosf(x2 / 10.0f * b2_pi); | ||||
|  | ||||
|                 b2EdgeShape shape; | ||||
|                 shape.Set(b2Vec2(x1, y1), b2Vec2(x2, y2)); | ||||
|                 ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|                 x1 = x2; | ||||
|                 y1 = y2; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|  | ||||
|         float32 x = RandomFloat(-10.0f, 10.0f); | ||||
|         float32 y = RandomFloat(10.0f, 20.0f); | ||||
|         bd.position.Set(x, y); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|         bd.type = b2_dynamicBody; | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.friction = 0.3f; | ||||
|             fd.density = 20.0f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.friction = 0.3f; | ||||
|             fd.density = 20.0f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool advanceRay = settings->pause == 0 || settings->singleStep; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         float32 L = 25.0f; | ||||
|         b2Vec2 point1(0.0f, 10.0f); | ||||
|         b2Vec2 d(L * cosf(m_angle), -L * b2Abs(sinf(m_angle))); | ||||
|         b2Vec2 point2 = point1 + d; | ||||
|  | ||||
|         EdgeShapesCallback callback; | ||||
|  | ||||
|         m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|         if (callback.m_fixture) | ||||
|         { | ||||
|             m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|  | ||||
|             m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|  | ||||
|             b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|             m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|         } | ||||
|  | ||||
|         if (advanceRay) | ||||
|         { | ||||
|             m_angle += 0.25f * b2_pi / 180.0f; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new EdgeShapes; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[e_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
|  | ||||
|     float32 m_angle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,109 +1,109 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef EDGE_TEST_H | ||||
| #define EDGE_TEST_H | ||||
|  | ||||
| class EdgeTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     EdgeTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 v1(-10.0f, 0.0f), v2(-7.0f, -2.0f), v3(-4.0f, 0.0f); | ||||
|             b2Vec2 v4(0.0f, 0.0f), v5(4.0f, 0.0f), v6(7.0f, 2.0f), v7(10.0f, 0.0f); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             shape.Set(v1, v2); | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex3 = v3; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v2, v3); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v1; | ||||
|             shape.m_vertex3 = v4; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v3, v4); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v2; | ||||
|             shape.m_vertex3 = v5; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v4, v5); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v3; | ||||
|             shape.m_vertex3 = v6; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v5, v6); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v4; | ||||
|             shape.m_vertex3 = v7; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v6, v7); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_vertex0 = v5; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-0.5f, 0.6f); | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(1.0f, 0.6f); | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new EdgeTest; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef EDGE_TEST_H | ||||
| #define EDGE_TEST_H | ||||
|  | ||||
| class EdgeTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     EdgeTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 v1(-10.0f, 0.0f), v2(-7.0f, -2.0f), v3(-4.0f, 0.0f); | ||||
|             b2Vec2 v4(0.0f, 0.0f), v5(4.0f, 0.0f), v6(7.0f, 2.0f), v7(10.0f, 0.0f); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|  | ||||
|             shape.Set(v1, v2); | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex3 = v3; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v2, v3); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v1; | ||||
|             shape.m_vertex3 = v4; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v3, v4); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v2; | ||||
|             shape.m_vertex3 = v5; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v4, v5); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v3; | ||||
|             shape.m_vertex3 = v6; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v5, v6); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_hasVertex3 = true; | ||||
|             shape.m_vertex0 = v4; | ||||
|             shape.m_vertex3 = v7; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(v6, v7); | ||||
|             shape.m_hasVertex0 = true; | ||||
|             shape.m_vertex0 = v5; | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-0.5f, 0.6f); | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(1.0f, 0.6f); | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new EdgeTest; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,187 +1,187 @@ | ||||
| /* | ||||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef GEARS_H | ||||
| #define GEARS_H | ||||
|  | ||||
| class Gears : public Test | ||||
| { | ||||
| public: | ||||
|     Gears() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Gears co | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 1.0f; | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 5.0f); | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 2.0f; | ||||
|  | ||||
|             b2BodyDef bd1; | ||||
|             bd1.type = b2_staticBody; | ||||
|             bd1.position.Set(10.0f, 9.0f); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|             body1->CreateFixture(&circle1, 0.0f); | ||||
|  | ||||
|             b2BodyDef bd2; | ||||
|             bd2.type = b2_dynamicBody; | ||||
|             bd2.position.Set(10.0f, 8.0f); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|             body2->CreateFixture(&box, 5.0f); | ||||
|  | ||||
|             b2BodyDef bd3; | ||||
|             bd3.type = b2_dynamicBody; | ||||
|             bd3.position.Set(10.0f, 6.0f); | ||||
|             b2Body* body3 = m_world->CreateBody(&bd3); | ||||
|             body3->CreateFixture(&circle2, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd1; | ||||
|             jd1.Initialize(body2, body1, bd1.position); | ||||
|             b2Joint* joint1 = m_world->CreateJoint(&jd1); | ||||
|  | ||||
|             b2RevoluteJointDef jd2; | ||||
|             jd2.Initialize(body2, body3, bd3.position); | ||||
|             b2Joint* joint2 = m_world->CreateJoint(&jd2); | ||||
|  | ||||
|             b2GearJointDef jd4; | ||||
|             jd4.bodyA = body1; | ||||
|             jd4.bodyB = body3; | ||||
|             jd4.joint1 = joint1; | ||||
|             jd4.joint2 = joint2; | ||||
|             jd4.ratio = circle2.m_radius / circle1.m_radius; | ||||
|             m_world->CreateJoint(&jd4); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 1.0f; | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 2.0f; | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 5.0f); | ||||
|  | ||||
|             b2BodyDef bd1; | ||||
|             bd1.type = b2_dynamicBody; | ||||
|             bd1.position.Set(-3.0f, 12.0f); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|             body1->CreateFixture(&circle1, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd1; | ||||
|             jd1.bodyA = ground; | ||||
|             jd1.bodyB = body1; | ||||
|             jd1.localAnchorA = ground->GetLocalPoint(bd1.position); | ||||
|             jd1.localAnchorB = body1->GetLocalPoint(bd1.position); | ||||
|             jd1.referenceAngle = body1->GetAngle() - ground->GetAngle(); | ||||
|             m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1); | ||||
|  | ||||
|             b2BodyDef bd2; | ||||
|             bd2.type = b2_dynamicBody; | ||||
|             bd2.position.Set(0.0f, 12.0f); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|             body2->CreateFixture(&circle2, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd2; | ||||
|             jd2.Initialize(ground, body2, bd2.position); | ||||
|             m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2); | ||||
|  | ||||
|             b2BodyDef bd3; | ||||
|             bd3.type = b2_dynamicBody; | ||||
|             bd3.position.Set(2.5f, 12.0f); | ||||
|             b2Body* body3 = m_world->CreateBody(&bd3); | ||||
|             body3->CreateFixture(&box, 5.0f); | ||||
|  | ||||
|             b2PrismaticJointDef jd3; | ||||
|             jd3.Initialize(ground, body3, bd3.position, b2Vec2(0.0f, 1.0f)); | ||||
|             jd3.lowerTranslation = -5.0f; | ||||
|             jd3.upperTranslation = 5.0f; | ||||
|             jd3.enableLimit = true; | ||||
|  | ||||
|             m_joint3 = (b2PrismaticJoint*)m_world->CreateJoint(&jd3); | ||||
|  | ||||
|             b2GearJointDef jd4; | ||||
|             jd4.bodyA = body1; | ||||
|             jd4.bodyB = body2; | ||||
|             jd4.joint1 = m_joint1; | ||||
|             jd4.joint2 = m_joint2; | ||||
|             jd4.ratio = circle2.m_radius / circle1.m_radius; | ||||
|             m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4); | ||||
|  | ||||
|             b2GearJointDef jd5; | ||||
|             jd5.bodyA = body2; | ||||
|             jd5.bodyB = body3; | ||||
|             jd5.joint1 = m_joint2; | ||||
|             jd5.joint2 = m_joint3; | ||||
|             jd5.ratio = -1.0f / circle2.m_radius; | ||||
|             m_joint5 = (b2GearJoint*)m_world->CreateJoint(&jd5); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 0: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         float32 ratio, value; | ||||
|  | ||||
|         ratio = m_joint4->GetRatio(); | ||||
|         value = m_joint1->GetJointAngle() + ratio * m_joint2->GetJointAngle(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "theta1 + %4.2f * theta2 = %4.2f", (float) ratio, (float) value); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         ratio = m_joint5->GetRatio(); | ||||
|         value = m_joint2->GetJointAngle() + ratio * m_joint3->GetJointTranslation(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "theta2 + %4.2f * delta = %4.2f", (float) ratio, (float) value); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Gears; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint1; | ||||
|     b2RevoluteJoint* m_joint2; | ||||
|     b2PrismaticJoint* m_joint3; | ||||
|     b2GearJoint* m_joint4; | ||||
|     b2GearJoint* m_joint5; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef GEARS_H | ||||
| #define GEARS_H | ||||
|  | ||||
| class Gears : public Test | ||||
| { | ||||
| public: | ||||
|     Gears() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Gears co | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 1.0f; | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 5.0f); | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 2.0f; | ||||
|  | ||||
|             b2BodyDef bd1; | ||||
|             bd1.type = b2_staticBody; | ||||
|             bd1.position.Set(10.0f, 9.0f); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|             body1->CreateFixture(&circle1, 0.0f); | ||||
|  | ||||
|             b2BodyDef bd2; | ||||
|             bd2.type = b2_dynamicBody; | ||||
|             bd2.position.Set(10.0f, 8.0f); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|             body2->CreateFixture(&box, 5.0f); | ||||
|  | ||||
|             b2BodyDef bd3; | ||||
|             bd3.type = b2_dynamicBody; | ||||
|             bd3.position.Set(10.0f, 6.0f); | ||||
|             b2Body* body3 = m_world->CreateBody(&bd3); | ||||
|             body3->CreateFixture(&circle2, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd1; | ||||
|             jd1.Initialize(body2, body1, bd1.position); | ||||
|             b2Joint* joint1 = m_world->CreateJoint(&jd1); | ||||
|  | ||||
|             b2RevoluteJointDef jd2; | ||||
|             jd2.Initialize(body2, body3, bd3.position); | ||||
|             b2Joint* joint2 = m_world->CreateJoint(&jd2); | ||||
|  | ||||
|             b2GearJointDef jd4; | ||||
|             jd4.bodyA = body1; | ||||
|             jd4.bodyB = body3; | ||||
|             jd4.joint1 = joint1; | ||||
|             jd4.joint2 = joint2; | ||||
|             jd4.ratio = circle2.m_radius / circle1.m_radius; | ||||
|             m_world->CreateJoint(&jd4); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle1; | ||||
|             circle1.m_radius = 1.0f; | ||||
|  | ||||
|             b2CircleShape circle2; | ||||
|             circle2.m_radius = 2.0f; | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(0.5f, 5.0f); | ||||
|  | ||||
|             b2BodyDef bd1; | ||||
|             bd1.type = b2_dynamicBody; | ||||
|             bd1.position.Set(-3.0f, 12.0f); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|             body1->CreateFixture(&circle1, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd1; | ||||
|             jd1.bodyA = ground; | ||||
|             jd1.bodyB = body1; | ||||
|             jd1.localAnchorA = ground->GetLocalPoint(bd1.position); | ||||
|             jd1.localAnchorB = body1->GetLocalPoint(bd1.position); | ||||
|             jd1.referenceAngle = body1->GetAngle() - ground->GetAngle(); | ||||
|             m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1); | ||||
|  | ||||
|             b2BodyDef bd2; | ||||
|             bd2.type = b2_dynamicBody; | ||||
|             bd2.position.Set(0.0f, 12.0f); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|             body2->CreateFixture(&circle2, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd2; | ||||
|             jd2.Initialize(ground, body2, bd2.position); | ||||
|             m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2); | ||||
|  | ||||
|             b2BodyDef bd3; | ||||
|             bd3.type = b2_dynamicBody; | ||||
|             bd3.position.Set(2.5f, 12.0f); | ||||
|             b2Body* body3 = m_world->CreateBody(&bd3); | ||||
|             body3->CreateFixture(&box, 5.0f); | ||||
|  | ||||
|             b2PrismaticJointDef jd3; | ||||
|             jd3.Initialize(ground, body3, bd3.position, b2Vec2(0.0f, 1.0f)); | ||||
|             jd3.lowerTranslation = -5.0f; | ||||
|             jd3.upperTranslation = 5.0f; | ||||
|             jd3.enableLimit = true; | ||||
|  | ||||
|             m_joint3 = (b2PrismaticJoint*)m_world->CreateJoint(&jd3); | ||||
|  | ||||
|             b2GearJointDef jd4; | ||||
|             jd4.bodyA = body1; | ||||
|             jd4.bodyB = body2; | ||||
|             jd4.joint1 = m_joint1; | ||||
|             jd4.joint2 = m_joint2; | ||||
|             jd4.ratio = circle2.m_radius / circle1.m_radius; | ||||
|             m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4); | ||||
|  | ||||
|             b2GearJointDef jd5; | ||||
|             jd5.bodyA = body2; | ||||
|             jd5.bodyB = body3; | ||||
|             jd5.joint1 = m_joint2; | ||||
|             jd5.joint2 = m_joint3; | ||||
|             jd5.ratio = -1.0f / circle2.m_radius; | ||||
|             m_joint5 = (b2GearJoint*)m_world->CreateJoint(&jd5); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 0: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         float32 ratio, value; | ||||
|  | ||||
|         ratio = m_joint4->GetRatio(); | ||||
|         value = m_joint1->GetJointAngle() + ratio * m_joint2->GetJointAngle(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "theta1 + %4.2f * theta2 = %4.2f", (float) ratio, (float) value); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         ratio = m_joint5->GetRatio(); | ||||
|         value = m_joint2->GetJointAngle() + ratio * m_joint3->GetJointTranslation(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "theta2 + %4.2f * delta = %4.2f", (float) ratio, (float) value); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Gears; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint1; | ||||
|     b2RevoluteJoint* m_joint2; | ||||
|     b2PrismaticJoint* m_joint3; | ||||
|     b2GearJoint* m_joint4; | ||||
|     b2GearJoint* m_joint5; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,120 +1,120 @@ | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ONE_SIDED_PLATFORM_H | ||||
| #define ONE_SIDED_PLATFORM_H | ||||
|  | ||||
| class OneSidedPlatform : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum State | ||||
|     { | ||||
|         e_unknown, | ||||
|         e_above, | ||||
|         e_below | ||||
|     }; | ||||
|  | ||||
|     OneSidedPlatform() | ||||
|     { | ||||
|         // Ground | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Platform | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(3.0f, 0.5f); | ||||
|             m_platform = body->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             m_bottom = 10.0f - 0.5f; | ||||
|             m_top = 10.0f + 0.5f; | ||||
|         } | ||||
|  | ||||
|         // Actor | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             m_radius = 0.5f; | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = m_radius; | ||||
|             m_character = body->CreateFixture(&shape, 20.0f); | ||||
|  | ||||
|             body->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|  | ||||
|             m_state = e_unknown; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) | ||||
|     { | ||||
|         Test::PreSolve(contact, oldManifold); | ||||
|  | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA != m_platform && fixtureA != m_character) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (fixtureB != m_platform && fixtureB != m_character) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         b2Vec2 position = m_character->GetBody()->GetPosition(); | ||||
|  | ||||
|         if (position.y < m_top + m_radius - 3.0f * b2_linearSlop) | ||||
|         { | ||||
|             contact->SetEnabled(false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new OneSidedPlatform; | ||||
|     } | ||||
|  | ||||
|     float32 m_radius, m_top, m_bottom; | ||||
|     State m_state; | ||||
|     b2Fixture* m_platform; | ||||
|     b2Fixture* m_character; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ONE_SIDED_PLATFORM_H | ||||
| #define ONE_SIDED_PLATFORM_H | ||||
|  | ||||
| class OneSidedPlatform : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum State | ||||
|     { | ||||
|         e_unknown, | ||||
|         e_above, | ||||
|         e_below | ||||
|     }; | ||||
|  | ||||
|     OneSidedPlatform() | ||||
|     { | ||||
|         // Ground | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Platform | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(3.0f, 0.5f); | ||||
|             m_platform = body->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             m_bottom = 10.0f - 0.5f; | ||||
|             m_top = 10.0f + 0.5f; | ||||
|         } | ||||
|  | ||||
|         // Actor | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 12.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             m_radius = 0.5f; | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = m_radius; | ||||
|             m_character = body->CreateFixture(&shape, 20.0f); | ||||
|  | ||||
|             body->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|  | ||||
|             m_state = e_unknown; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) | ||||
|     { | ||||
|         Test::PreSolve(contact, oldManifold); | ||||
|  | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA != m_platform && fixtureA != m_character) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (fixtureB != m_platform && fixtureB != m_character) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         b2Vec2 position = m_character->GetBody()->GetPosition(); | ||||
|  | ||||
|         if (position.y < m_top + m_radius - 3.0f * b2_linearSlop) | ||||
|         { | ||||
|             contact->SetEnabled(false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new OneSidedPlatform; | ||||
|     } | ||||
|  | ||||
|     float32 m_radius, m_top, m_bottom; | ||||
|     State m_state; | ||||
|     b2Fixture* m_platform; | ||||
|     b2Fixture* m_character; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,169 +1,169 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PINBALL_H | ||||
| #define PINBALL_H | ||||
|  | ||||
| /// This tests bullet collision and provides an example of a gameplay scenario. | ||||
| /// This also uses a loop shape. | ||||
| class Pinball : public Test | ||||
| { | ||||
| public: | ||||
|     Pinball() | ||||
|     { | ||||
|         // Ground body | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[5]; | ||||
|             vs[0].Set(0.0f, -2.0f); | ||||
|             vs[1].Set(8.0f, 6.0f); | ||||
|             vs[2].Set(8.0f, 20.0f); | ||||
|             vs[3].Set(-8.0f, 20.0f); | ||||
|             vs[4].Set(-8.0f, 6.0f); | ||||
|  | ||||
|             b2ChainShape loop; | ||||
|             loop.CreateLoop(vs, 5); | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &loop; | ||||
|             fd.density = 0.0f; | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Flippers | ||||
|         { | ||||
|             b2Vec2 p1(-2.0f, 0.0f), p2(2.0f, 0.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position = p1; | ||||
|             b2Body* leftFlipper = m_world->CreateBody(&bd); | ||||
|  | ||||
|             bd.position = p2; | ||||
|             b2Body* rightFlipper = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(1.75f, 0.1f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &box; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             leftFlipper->CreateFixture(&fd); | ||||
|             rightFlipper->CreateFixture(&fd); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.bodyA = ground; | ||||
|             jd.localAnchorB.SetZero(); | ||||
|             jd.enableMotor = true; | ||||
|             jd.maxMotorTorque = 1000.0f; | ||||
|             jd.enableLimit = true; | ||||
|  | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.localAnchorA = p1; | ||||
|             jd.bodyB = leftFlipper; | ||||
|             jd.lowerAngle = -30.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 5.0f * b2_pi / 180.0f; | ||||
|             m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.localAnchorA = p2; | ||||
|             jd.bodyB = rightFlipper; | ||||
|             jd.lowerAngle = -5.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 30.0f * b2_pi / 180.0f; | ||||
|             m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(1.0f, 15.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.bullet = true; | ||||
|  | ||||
|             m_ball = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.2f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             m_ball->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_button = false; | ||||
|     } | ||||
|  | ||||
|     void Step() | ||||
|     { | ||||
|         if (m_button) | ||||
|         { | ||||
|             m_leftJoint->SetMotorSpeed(20.0f); | ||||
|             m_rightJoint->SetMotorSpeed(-20.0f); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_leftJoint->SetMotorSpeed(-10.0f); | ||||
|             m_rightJoint->SetMotorSpeed(10.0f); | ||||
|         } | ||||
|  | ||||
| //      Test::Step(settings); | ||||
| // | ||||
| //      m_debugDraw.DrawString(5, m_textLine, "Press 'a' to control the flippers"); | ||||
| //      m_textLine += 15; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|         case 'A': | ||||
|             m_button = true; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void KeyboardUp(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|         case 'A': | ||||
|             m_button = false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pinball; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_leftJoint; | ||||
|     b2RevoluteJoint* m_rightJoint; | ||||
|     b2Body* m_ball; | ||||
|     bool m_button; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PINBALL_H | ||||
| #define PINBALL_H | ||||
|  | ||||
| /// This tests bullet collision and provides an example of a gameplay scenario. | ||||
| /// This also uses a loop shape. | ||||
| class Pinball : public Test | ||||
| { | ||||
| public: | ||||
|     Pinball() | ||||
|     { | ||||
|         // Ground body | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2Vec2 vs[5]; | ||||
|             vs[0].Set(0.0f, -2.0f); | ||||
|             vs[1].Set(8.0f, 6.0f); | ||||
|             vs[2].Set(8.0f, 20.0f); | ||||
|             vs[3].Set(-8.0f, 20.0f); | ||||
|             vs[4].Set(-8.0f, 6.0f); | ||||
|  | ||||
|             b2ChainShape loop; | ||||
|             loop.CreateLoop(vs, 5); | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &loop; | ||||
|             fd.density = 0.0f; | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         // Flippers | ||||
|         { | ||||
|             b2Vec2 p1(-2.0f, 0.0f), p2(2.0f, 0.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position = p1; | ||||
|             b2Body* leftFlipper = m_world->CreateBody(&bd); | ||||
|  | ||||
|             bd.position = p2; | ||||
|             b2Body* rightFlipper = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape box; | ||||
|             box.SetAsBox(1.75f, 0.1f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &box; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             leftFlipper->CreateFixture(&fd); | ||||
|             rightFlipper->CreateFixture(&fd); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.bodyA = ground; | ||||
|             jd.localAnchorB.SetZero(); | ||||
|             jd.enableMotor = true; | ||||
|             jd.maxMotorTorque = 1000.0f; | ||||
|             jd.enableLimit = true; | ||||
|  | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.localAnchorA = p1; | ||||
|             jd.bodyB = leftFlipper; | ||||
|             jd.lowerAngle = -30.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 5.0f * b2_pi / 180.0f; | ||||
|             m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.motorSpeed = 0.0f; | ||||
|             jd.localAnchorA = p2; | ||||
|             jd.bodyB = rightFlipper; | ||||
|             jd.lowerAngle = -5.0f * b2_pi / 180.0f; | ||||
|             jd.upperAngle = 30.0f * b2_pi / 180.0f; | ||||
|             m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         // Circle character | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(1.0f, 15.0f); | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.bullet = true; | ||||
|  | ||||
|             m_ball = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.2f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             m_ball->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_button = false; | ||||
|     } | ||||
|  | ||||
|     void Step() | ||||
|     { | ||||
|         if (m_button) | ||||
|         { | ||||
|             m_leftJoint->SetMotorSpeed(20.0f); | ||||
|             m_rightJoint->SetMotorSpeed(-20.0f); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_leftJoint->SetMotorSpeed(-10.0f); | ||||
|             m_rightJoint->SetMotorSpeed(10.0f); | ||||
|         } | ||||
|  | ||||
| //      Test::Step(settings); | ||||
| // | ||||
| //      m_debugDraw.DrawString(5, m_textLine, "Press 'a' to control the flippers"); | ||||
| //      m_textLine += 15; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|         case 'A': | ||||
|             m_button = true; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void KeyboardUp(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|         case 'A': | ||||
|             m_button = false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pinball; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_leftJoint; | ||||
|     b2RevoluteJoint* m_rightJoint; | ||||
|     b2Body* m_ball; | ||||
|     bool m_button; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,122 +1,122 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef POLYCOLLISION_H | ||||
| #define POLYCOLLISION_H | ||||
|  | ||||
| class PolyCollision : public Test | ||||
| { | ||||
| public: | ||||
|     PolyCollision() | ||||
|     { | ||||
|         { | ||||
|             m_polygonA.SetAsBox(0.2f, 0.4f); | ||||
|             m_transformA.Set(b2Vec2(0.0f, 0.0f), 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygonB.SetAsBox(0.5f, 0.5f); | ||||
|             m_positionB.Set(19.345284f, 1.5632932f); | ||||
|             m_angleB = 1.9160721f; | ||||
|             m_transformB.Set(m_positionB, m_angleB); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new PolyCollision; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         B2_NOT_USED(settings); | ||||
|  | ||||
|         b2Manifold manifold; | ||||
|         b2CollidePolygons(&manifold, &m_polygonA, m_transformA, &m_polygonB, m_transformB); | ||||
|  | ||||
|         b2WorldManifold worldManifold; | ||||
|         worldManifold.Initialize(&manifold, m_transformA, m_polygonA.m_radius, m_transformB, m_polygonB.m_radius); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "point count = %d", manifold.pointCount); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         { | ||||
|             b2Color color(0.9f, 0.9f, 0.9f); | ||||
|             b2Vec2 v[b2_maxPolygonVertices]; | ||||
|             for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | ||||
|  | ||||
|             for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < manifold.pointCount; ++i) | ||||
|         { | ||||
|             m_debugDraw.DrawPoint(worldManifold.points[i], 4.0f, b2Color(0.9f, 0.3f, 0.3f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_positionB.x -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_positionB.x += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_positionB.y -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'w': | ||||
|             m_positionB.y += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_angleB += 0.1f * b2_pi; | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angleB -= 0.1f * b2_pi; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         m_transformB.Set(m_positionB, m_angleB); | ||||
|     } | ||||
|  | ||||
|     b2PolygonShape m_polygonA; | ||||
|     b2PolygonShape m_polygonB; | ||||
|  | ||||
|     b2Transform m_transformA; | ||||
|     b2Transform m_transformB; | ||||
|  | ||||
|     b2Vec2 m_positionB; | ||||
|     float32 m_angleB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef POLYCOLLISION_H | ||||
| #define POLYCOLLISION_H | ||||
|  | ||||
| class PolyCollision : public Test | ||||
| { | ||||
| public: | ||||
|     PolyCollision() | ||||
|     { | ||||
|         { | ||||
|             m_polygonA.SetAsBox(0.2f, 0.4f); | ||||
|             m_transformA.Set(b2Vec2(0.0f, 0.0f), 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygonB.SetAsBox(0.5f, 0.5f); | ||||
|             m_positionB.Set(19.345284f, 1.5632932f); | ||||
|             m_angleB = 1.9160721f; | ||||
|             m_transformB.Set(m_positionB, m_angleB); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new PolyCollision; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         B2_NOT_USED(settings); | ||||
|  | ||||
|         b2Manifold manifold; | ||||
|         b2CollidePolygons(&manifold, &m_polygonA, m_transformA, &m_polygonB, m_transformB); | ||||
|  | ||||
|         b2WorldManifold worldManifold; | ||||
|         worldManifold.Initialize(&manifold, m_transformA, m_polygonA.m_radius, m_transformB, m_polygonB.m_radius); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "point count = %d", manifold.pointCount); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         { | ||||
|             b2Color color(0.9f, 0.9f, 0.9f); | ||||
|             b2Vec2 v[b2_maxPolygonVertices]; | ||||
|             for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | ||||
|  | ||||
|             for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | ||||
|         } | ||||
|  | ||||
|         for (int32 i = 0; i < manifold.pointCount; ++i) | ||||
|         { | ||||
|             m_debugDraw.DrawPoint(worldManifold.points[i], 4.0f, b2Color(0.9f, 0.3f, 0.3f)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_positionB.x -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_positionB.x += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_positionB.y -= 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'w': | ||||
|             m_positionB.y += 0.1f; | ||||
|             break; | ||||
|  | ||||
|         case 'q': | ||||
|             m_angleB += 0.1f * b2_pi; | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angleB -= 0.1f * b2_pi; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         m_transformB.Set(m_positionB, m_angleB); | ||||
|     } | ||||
|  | ||||
|     b2PolygonShape m_polygonA; | ||||
|     b2PolygonShape m_polygonB; | ||||
|  | ||||
|     b2Transform m_transformA; | ||||
|     b2Transform m_transformB; | ||||
|  | ||||
|     b2Vec2 m_positionB; | ||||
|     float32 m_angleB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,295 +1,295 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef POLY_SHAPES_H | ||||
| #define POLY_SHAPES_H | ||||
|  | ||||
| /// This tests stacking. It also shows how to use b2World::Query | ||||
| /// and b2TestOverlap. | ||||
|  | ||||
| const int32 k_maxBodies = 256; | ||||
|  | ||||
| /// This callback is called by b2World::QueryAABB. We find all the fixtures | ||||
| /// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures | ||||
| /// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border. | ||||
| class PolyShapesCallback : public b2QueryCallback | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxCount = 4 | ||||
|     }; | ||||
|  | ||||
|     PolyShapesCallback() | ||||
|     { | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     void DrawFixture(b2Fixture* fixture) | ||||
|     { | ||||
|         b2Color color(0.95f, 0.95f, 0.6f); | ||||
|         const b2Transform& xf = fixture->GetBody()->GetTransform(); | ||||
|  | ||||
|         switch (fixture->GetType()) | ||||
|         { | ||||
|         case b2Shape::e_circle: | ||||
|             { | ||||
|                 b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); | ||||
|  | ||||
|                 b2Vec2 center = b2Mul(xf, circle->m_p); | ||||
|                 float32 radius = circle->m_radius; | ||||
|  | ||||
|                 m_debugDraw->DrawCircle(center, radius, color); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case b2Shape::e_polygon: | ||||
|             { | ||||
|                 b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); | ||||
|                 int32 vertexCount = poly->m_vertexCount; | ||||
|                 b2Assert(vertexCount <= b2_maxPolygonVertices); | ||||
|                 b2Vec2 vertices[b2_maxPolygonVertices]; | ||||
|  | ||||
|                 for (int32 i = 0; i < vertexCount; ++i) | ||||
|                 { | ||||
|                     vertices[i] = b2Mul(xf, poly->m_vertices[i]); | ||||
|                 } | ||||
|  | ||||
|                 m_debugDraw->DrawPolygon(vertices, vertexCount, color); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Called for each fixture found in the query AABB. | ||||
|     /// @return false to terminate the query. | ||||
|     bool ReportFixture(b2Fixture* fixture) | ||||
|     { | ||||
|         if (m_count == e_maxCount) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         b2Shape* shape = fixture->GetShape(); | ||||
|  | ||||
|         bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform); | ||||
|  | ||||
|         if (overlap) | ||||
|         { | ||||
|             DrawFixture(fixture); | ||||
|             ++m_count; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     b2CircleShape m_circle; | ||||
|     b2Transform m_transform; | ||||
|     b2Draw* m_debugDraw; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
| class PolyShapes : public Test | ||||
| { | ||||
| public: | ||||
|     PolyShapes() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|  | ||||
|         float32 x = RandomFloat(-2.0f, 2.0f); | ||||
|         bd.position.Set(x, 10.0f); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < k_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'a': | ||||
|             for (int32 i = 0; i < k_maxBodies; i += 2) | ||||
|             { | ||||
|                 if (m_bodies[i]) | ||||
|                 { | ||||
|                     bool active = m_bodies[i]->IsActive(); | ||||
|                     m_bodies[i]->SetActive(!active); | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         PolyShapesCallback callback; | ||||
|         callback.m_circle.m_radius = 2.0f; | ||||
|         callback.m_circle.m_p.Set(0.0f, 1.1f); | ||||
|         callback.m_transform.SetIdentity(); | ||||
|         callback.m_debugDraw = &m_debugDraw; | ||||
|  | ||||
|         b2AABB aabb; | ||||
|         callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0); | ||||
|  | ||||
|         m_world->QueryAABB(&callback, aabb); | ||||
|  | ||||
|         b2Color color(0.4f, 0.7f, 0.8f); | ||||
|         m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'd' to destroy a body"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new PolyShapes; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[k_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef POLY_SHAPES_H | ||||
| #define POLY_SHAPES_H | ||||
|  | ||||
| /// This tests stacking. It also shows how to use b2World::Query | ||||
| /// and b2TestOverlap. | ||||
|  | ||||
| const int32 k_maxBodies = 256; | ||||
|  | ||||
| /// This callback is called by b2World::QueryAABB. We find all the fixtures | ||||
| /// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures | ||||
| /// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border. | ||||
| class PolyShapesCallback : public b2QueryCallback | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxCount = 4 | ||||
|     }; | ||||
|  | ||||
|     PolyShapesCallback() | ||||
|     { | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     void DrawFixture(b2Fixture* fixture) | ||||
|     { | ||||
|         b2Color color(0.95f, 0.95f, 0.6f); | ||||
|         const b2Transform& xf = fixture->GetBody()->GetTransform(); | ||||
|  | ||||
|         switch (fixture->GetType()) | ||||
|         { | ||||
|         case b2Shape::e_circle: | ||||
|             { | ||||
|                 b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); | ||||
|  | ||||
|                 b2Vec2 center = b2Mul(xf, circle->m_p); | ||||
|                 float32 radius = circle->m_radius; | ||||
|  | ||||
|                 m_debugDraw->DrawCircle(center, radius, color); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case b2Shape::e_polygon: | ||||
|             { | ||||
|                 b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); | ||||
|                 int32 vertexCount = poly->m_vertexCount; | ||||
|                 b2Assert(vertexCount <= b2_maxPolygonVertices); | ||||
|                 b2Vec2 vertices[b2_maxPolygonVertices]; | ||||
|  | ||||
|                 for (int32 i = 0; i < vertexCount; ++i) | ||||
|                 { | ||||
|                     vertices[i] = b2Mul(xf, poly->m_vertices[i]); | ||||
|                 } | ||||
|  | ||||
|                 m_debugDraw->DrawPolygon(vertices, vertexCount, color); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Called for each fixture found in the query AABB. | ||||
|     /// @return false to terminate the query. | ||||
|     bool ReportFixture(b2Fixture* fixture) | ||||
|     { | ||||
|         if (m_count == e_maxCount) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         b2Shape* shape = fixture->GetShape(); | ||||
|  | ||||
|         bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform); | ||||
|  | ||||
|         if (overlap) | ||||
|         { | ||||
|             DrawFixture(fixture); | ||||
|             ++m_count; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     b2CircleShape m_circle; | ||||
|     b2Transform m_transform; | ||||
|     b2Draw* m_debugDraw; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
| class PolyShapes : public Test | ||||
| { | ||||
| public: | ||||
|     PolyShapes() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|  | ||||
|         float32 x = RandomFloat(-2.0f, 2.0f); | ||||
|         bd.position.Set(x, 10.0f); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < k_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'a': | ||||
|             for (int32 i = 0; i < k_maxBodies; i += 2) | ||||
|             { | ||||
|                 if (m_bodies[i]) | ||||
|                 { | ||||
|                     bool active = m_bodies[i]->IsActive(); | ||||
|                     m_bodies[i]->SetActive(!active); | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         PolyShapesCallback callback; | ||||
|         callback.m_circle.m_radius = 2.0f; | ||||
|         callback.m_circle.m_p.Set(0.0f, 1.1f); | ||||
|         callback.m_transform.SetIdentity(); | ||||
|         callback.m_debugDraw = &m_debugDraw; | ||||
|  | ||||
|         b2AABB aabb; | ||||
|         callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0); | ||||
|  | ||||
|         m_world->QueryAABB(&callback, aabb); | ||||
|  | ||||
|         b2Color color(0.4f, 0.7f, 0.8f); | ||||
|         m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 'd' to destroy a body"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new PolyShapes; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[k_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,107 +1,107 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PRISMATIC_H | ||||
| #define PRISMATIC_H | ||||
|  | ||||
| // The motor in this test gets smoother with higher velocity iterations. | ||||
| class Prismatic : public Test | ||||
| { | ||||
| public: | ||||
|     Prismatic() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.0f, 0.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-10.0f, 10.0f); | ||||
|             bd.angle = 0.5f * b2_pi; | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2PrismaticJointDef pjd; | ||||
|  | ||||
|             // Bouncy limit | ||||
|             b2Vec2 axis(2.0f, 1.0f); | ||||
|             axis.Normalize(); | ||||
|             pjd.Initialize(ground, body, b2Vec2(0.0f, 0.0f), axis); | ||||
|  | ||||
|             // Non-bouncy limit | ||||
|             //pjd.Initialize(ground, body, b2Vec2(-10.0f, 10.0f), b2Vec2(1.0f, 0.0f)); | ||||
|  | ||||
|             pjd.motorSpeed = 10.0f; | ||||
|             pjd.maxMotorForce = 10000.0f; | ||||
|             pjd.enableMotor = true; | ||||
|             pjd.lowerTranslation = 0.0f; | ||||
|             pjd.upperTranslation = 20.0f; | ||||
|             pjd.enableLimit = true; | ||||
|  | ||||
|             m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'l': | ||||
|             m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_joint->SetMotorSpeed(-m_joint->GetMotorSpeed()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motors, (s) speed"); | ||||
|         m_textLine += 15; | ||||
|         float32 force = m_joint->GetMotorForce(settings->hz); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Motor Force = %4.0f", (float) force); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Prismatic; | ||||
|     } | ||||
|  | ||||
|     b2PrismaticJoint* m_joint; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PRISMATIC_H | ||||
| #define PRISMATIC_H | ||||
|  | ||||
| // The motor in this test gets smoother with higher velocity iterations. | ||||
| class Prismatic : public Test | ||||
| { | ||||
| public: | ||||
|     Prismatic() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.0f, 0.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-10.0f, 10.0f); | ||||
|             bd.angle = 0.5f * b2_pi; | ||||
|             bd.allowSleep = false; | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2PrismaticJointDef pjd; | ||||
|  | ||||
|             // Bouncy limit | ||||
|             b2Vec2 axis(2.0f, 1.0f); | ||||
|             axis.Normalize(); | ||||
|             pjd.Initialize(ground, body, b2Vec2(0.0f, 0.0f), axis); | ||||
|  | ||||
|             // Non-bouncy limit | ||||
|             //pjd.Initialize(ground, body, b2Vec2(-10.0f, 10.0f), b2Vec2(1.0f, 0.0f)); | ||||
|  | ||||
|             pjd.motorSpeed = 10.0f; | ||||
|             pjd.maxMotorForce = 10000.0f; | ||||
|             pjd.enableMotor = true; | ||||
|             pjd.lowerTranslation = 0.0f; | ||||
|             pjd.upperTranslation = 20.0f; | ||||
|             pjd.enableLimit = true; | ||||
|  | ||||
|             m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'l': | ||||
|             m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_joint->SetMotorSpeed(-m_joint->GetMotorSpeed()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motors, (s) speed"); | ||||
|         m_textLine += 15; | ||||
|         float32 force = m_joint->GetMotorForce(settings->hz); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Motor Force = %4.0f", (float) force); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Prismatic; | ||||
|     } | ||||
|  | ||||
|     b2PrismaticJoint* m_joint; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,106 +1,106 @@ | ||||
| /* | ||||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PULLEYS_H | ||||
| #define PULLEYS_H | ||||
|  | ||||
| class Pulleys : public Test | ||||
| { | ||||
| public: | ||||
|     Pulleys() | ||||
|     { | ||||
|         float32 y = 16.0f; | ||||
|         float32 L = 12.0f; | ||||
|         float32 a = 1.0f; | ||||
|         float32 b = 2.0f; | ||||
|  | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|             edge.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             //ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             b2CircleShape circle; | ||||
|             circle.m_radius = 2.0f; | ||||
|  | ||||
|             circle.m_p.Set(-10.0f, y + b + L); | ||||
|             ground->CreateFixture(&circle, 0.0f); | ||||
|  | ||||
|             circle.m_p.Set(10.0f, y + b + L); | ||||
|             ground->CreateFixture(&circle, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, b); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             //bd.fixedRotation = true; | ||||
|             bd.position.Set(-10.0f, y); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd); | ||||
|             body1->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(10.0f, y); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd); | ||||
|             body2->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2PulleyJointDef pulleyDef; | ||||
|             b2Vec2 anchor1(-10.0f, y + b); | ||||
|             b2Vec2 anchor2(10.0f, y + b); | ||||
|             b2Vec2 groundAnchor1(-10.0f, y + b + L); | ||||
|             b2Vec2 groundAnchor2(10.0f, y + b + L); | ||||
|             pulleyDef.Initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 1.5f); | ||||
|  | ||||
|             m_joint1 = (b2PulleyJoint*)m_world->CreateJoint(&pulleyDef); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 0: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         float32 ratio = m_joint1->GetRatio(); | ||||
|         float32 L = m_joint1->GetLengthA() + ratio * m_joint1->GetLengthB(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "L1 + %4.2f * L2 = %4.2f", (float) ratio, (float) L); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pulleys; | ||||
|     } | ||||
|  | ||||
|     b2PulleyJoint* m_joint1; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PULLEYS_H | ||||
| #define PULLEYS_H | ||||
|  | ||||
| class Pulleys : public Test | ||||
| { | ||||
| public: | ||||
|     Pulleys() | ||||
|     { | ||||
|         float32 y = 16.0f; | ||||
|         float32 L = 12.0f; | ||||
|         float32 a = 1.0f; | ||||
|         float32 b = 2.0f; | ||||
|  | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape edge; | ||||
|             edge.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             //ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             b2CircleShape circle; | ||||
|             circle.m_radius = 2.0f; | ||||
|  | ||||
|             circle.m_p.Set(-10.0f, y + b + L); | ||||
|             ground->CreateFixture(&circle, 0.0f); | ||||
|  | ||||
|             circle.m_p.Set(10.0f, y + b + L); | ||||
|             ground->CreateFixture(&circle, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, b); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             //bd.fixedRotation = true; | ||||
|             bd.position.Set(-10.0f, y); | ||||
|             b2Body* body1 = m_world->CreateBody(&bd); | ||||
|             body1->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(10.0f, y); | ||||
|             b2Body* body2 = m_world->CreateBody(&bd); | ||||
|             body2->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2PulleyJointDef pulleyDef; | ||||
|             b2Vec2 anchor1(-10.0f, y + b); | ||||
|             b2Vec2 anchor2(10.0f, y + b); | ||||
|             b2Vec2 groundAnchor1(-10.0f, y + b + L); | ||||
|             b2Vec2 groundAnchor2(10.0f, y + b + L); | ||||
|             pulleyDef.Initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 1.5f); | ||||
|  | ||||
|             m_joint1 = (b2PulleyJoint*)m_world->CreateJoint(&pulleyDef); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 0: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         float32 ratio = m_joint1->GetRatio(); | ||||
|         float32 L = m_joint1->GetLengthA() + ratio * m_joint1->GetLengthB(); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "L1 + %4.2f * L2 = %4.2f", (float) ratio, (float) L); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pulleys; | ||||
|     } | ||||
|  | ||||
|     b2PulleyJoint* m_joint1; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,89 +1,89 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PYRAMID_H | ||||
| #define PYRAMID_H | ||||
|  | ||||
| class Pyramid : public Test | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_count = 20 | ||||
|     }; | ||||
|  | ||||
|     Pyramid() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, a); | ||||
|  | ||||
|             b2Vec2 x(-7.0f, 0.75f); | ||||
|             b2Vec2 y; | ||||
|             b2Vec2 deltaX(0.5625f, 1.25f); | ||||
|             b2Vec2 deltaY(1.125f, 0.0f); | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 y = x; | ||||
|  | ||||
|                 for (int32 j = i; j < e_count; ++j) | ||||
|                 { | ||||
|                     b2BodyDef bd; | ||||
|                     bd.type = b2_dynamicBody; | ||||
|                     bd.position = y; | ||||
|                     b2Body* body = m_world->CreateBody(&bd); | ||||
|                     body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|                     y += deltaY; | ||||
|                 } | ||||
|  | ||||
|                 x += deltaX; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; | ||||
|  | ||||
|         //if (m_stepCount == 400) | ||||
|         //{ | ||||
|         //  tree->RebuildBottomUp(); | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pyramid; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef PYRAMID_H | ||||
| #define PYRAMID_H | ||||
|  | ||||
| class Pyramid : public Test | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_count = 20 | ||||
|     }; | ||||
|  | ||||
|     Pyramid() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, a); | ||||
|  | ||||
|             b2Vec2 x(-7.0f, 0.75f); | ||||
|             b2Vec2 y; | ||||
|             b2Vec2 deltaX(0.5625f, 1.25f); | ||||
|             b2Vec2 deltaY(1.125f, 0.0f); | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 y = x; | ||||
|  | ||||
|                 for (int32 j = i; j < e_count; ++j) | ||||
|                 { | ||||
|                     b2BodyDef bd; | ||||
|                     bd.type = b2_dynamicBody; | ||||
|                     bd.position = y; | ||||
|                     b2Body* body = m_world->CreateBody(&bd); | ||||
|                     body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|                     y += deltaY; | ||||
|                 } | ||||
|  | ||||
|                 x += deltaX; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; | ||||
|  | ||||
|         //if (m_stepCount == 400) | ||||
|         //{ | ||||
|         //  tree->RebuildBottomUp(); | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Pyramid; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,440 +1,440 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef RAY_CAST_H | ||||
| #define RAY_CAST_H | ||||
|  | ||||
| // This test demonstrates how to use the world ray-cast feature. | ||||
| // NOTE: we are intentionally filtering one of the polygons, therefore | ||||
| // the ray will always miss one type of polygon. | ||||
|  | ||||
| // This callback finds the closest hit. Polygon 0 is filtered. | ||||
| class RayCastClosestCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     RayCastClosestCallback() | ||||
|     { | ||||
|         m_hit = false; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_hit = true; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|         return fraction; | ||||
|     } | ||||
|  | ||||
|     bool m_hit; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| // This callback finds any hit. Polygon 0 is filtered. | ||||
| class RayCastAnyCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     RayCastAnyCallback() | ||||
|     { | ||||
|         m_hit = false; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_hit = true; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|         return 0.0f; | ||||
|     } | ||||
|  | ||||
|     bool m_hit; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| // This ray cast collects multiple hits along the ray. Polygon 0 is filtered. | ||||
| class RayCastMultipleCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_maxCount = 3 | ||||
|     }; | ||||
|  | ||||
|     RayCastMultipleCallback() | ||||
|     { | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         b2Assert(m_count < e_maxCount); | ||||
|  | ||||
|         m_points[m_count] = point; | ||||
|         m_normals[m_count] = normal; | ||||
|         ++m_count; | ||||
|  | ||||
|         if (m_count == e_maxCount) | ||||
|         { | ||||
|             return 0.0f; | ||||
|         } | ||||
|  | ||||
|         return 1.0f; | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_points[e_maxCount]; | ||||
|     b2Vec2 m_normals[e_maxCount]; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class RayCast : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxBodies = 256 | ||||
|     }; | ||||
|  | ||||
|     enum Mode | ||||
|     { | ||||
|         e_closest, | ||||
|         e_any, | ||||
|         e_multiple | ||||
|     }; | ||||
|  | ||||
|     RayCast() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|  | ||||
|         m_mode = e_closest; | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|  | ||||
|         float32 x = RandomFloat(-10.0f, 10.0f); | ||||
|         float32 y = RandomFloat(0.0f, 20.0f); | ||||
|         bd.position.Set(x, y); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|  | ||||
|         m_userData[m_bodyIndex] = index; | ||||
|         bd.userData = m_userData + m_bodyIndex; | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.friction = 0.3f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             if (m_mode == e_closest) | ||||
|             { | ||||
|                 m_mode = e_any; | ||||
|             } | ||||
|             else if (m_mode == e_any) | ||||
|             { | ||||
|                 m_mode = e_multiple; | ||||
|             } | ||||
|             else if (m_mode == e_multiple) | ||||
|             { | ||||
|                 m_mode = e_closest; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool advanceRay = settings->pause == 0 || settings->singleStep; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, m to change the mode"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Mode = %d", m_mode); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         float32 L = 11.0f; | ||||
|         b2Vec2 point1(0.0f, 10.0f); | ||||
|         b2Vec2 d(L * cosf(m_angle), L * sinf(m_angle)); | ||||
|         b2Vec2 point2 = point1 + d; | ||||
|  | ||||
|         if (m_mode == e_closest) | ||||
|         { | ||||
|             RayCastClosestCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|             if (callback.m_hit) | ||||
|             { | ||||
|                 m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|                 m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|             } | ||||
|         } | ||||
|         else if (m_mode == e_any) | ||||
|         { | ||||
|             RayCastAnyCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|             if (callback.m_hit) | ||||
|             { | ||||
|                 m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|                 m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|             } | ||||
|         } | ||||
|         else if (m_mode == e_multiple) | ||||
|         { | ||||
|             RayCastMultipleCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|             m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|  | ||||
|             for (int32 i = 0; i < callback.m_count; ++i) | ||||
|             { | ||||
|                 b2Vec2 p = callback.m_points[i]; | ||||
|                 b2Vec2 n = callback.m_normals[i]; | ||||
|                 m_debugDraw.DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = p + 0.5f * n; | ||||
|                 m_debugDraw.DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (advanceRay) | ||||
|         { | ||||
|             m_angle += 0.25f * b2_pi / 180.0f; | ||||
|         } | ||||
|  | ||||
| #if 0 | ||||
|         // This case was failing. | ||||
|         { | ||||
|             b2Vec2 vertices[4]; | ||||
|             //vertices[0].Set(-22.875f, -3.0f); | ||||
|             //vertices[1].Set(22.875f, -3.0f); | ||||
|             //vertices[2].Set(22.875f, 3.0f); | ||||
|             //vertices[3].Set(-22.875f, 3.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             //shape.Set(vertices, 4); | ||||
|             shape.SetAsBox(22.875f, 3.0f); | ||||
|  | ||||
|             b2RayCastInput input; | ||||
|             input.p1.Set(10.2725f,1.71372f); | ||||
|             input.p2.Set(10.2353f,2.21807f); | ||||
|             //input.maxFraction = 0.567623f; | ||||
|             input.maxFraction = 0.56762173f; | ||||
|  | ||||
|             b2Transform xf; | ||||
|             xf.SetIdentity(); | ||||
|             xf.position.Set(23.0f, 5.0f); | ||||
|  | ||||
|             b2RayCastOutput output; | ||||
|             bool hit; | ||||
|             hit = shape.RayCast(&output, input, xf); | ||||
|             hit = false; | ||||
|  | ||||
|             b2Color color(1.0f, 1.0f, 1.0f); | ||||
|             b2Vec2 vs[4]; | ||||
|             for (int32 i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 vs[i] = b2Mul(xf, shape.m_vertices[i]); | ||||
|             } | ||||
|  | ||||
|             m_debugDraw.DrawPolygon(vs, 4, color); | ||||
|             m_debugDraw.DrawSegment(input.p1, input.p2, color); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new RayCast; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[e_maxBodies]; | ||||
|     int32 m_userData[e_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
|  | ||||
|     float32 m_angle; | ||||
|  | ||||
|     Mode m_mode; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef RAY_CAST_H | ||||
| #define RAY_CAST_H | ||||
|  | ||||
| // This test demonstrates how to use the world ray-cast feature. | ||||
| // NOTE: we are intentionally filtering one of the polygons, therefore | ||||
| // the ray will always miss one type of polygon. | ||||
|  | ||||
| // This callback finds the closest hit. Polygon 0 is filtered. | ||||
| class RayCastClosestCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     RayCastClosestCallback() | ||||
|     { | ||||
|         m_hit = false; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_hit = true; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|         return fraction; | ||||
|     } | ||||
|  | ||||
|     bool m_hit; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| // This callback finds any hit. Polygon 0 is filtered. | ||||
| class RayCastAnyCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     RayCastAnyCallback() | ||||
|     { | ||||
|         m_hit = false; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_hit = true; | ||||
|         m_point = point; | ||||
|         m_normal = normal; | ||||
|         return 0.0f; | ||||
|     } | ||||
|  | ||||
|     bool m_hit; | ||||
|     b2Vec2 m_point; | ||||
|     b2Vec2 m_normal; | ||||
| }; | ||||
|  | ||||
| // This ray cast collects multiple hits along the ray. Polygon 0 is filtered. | ||||
| class RayCastMultipleCallback : public b2RayCastCallback | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_maxCount = 3 | ||||
|     }; | ||||
|  | ||||
|     RayCastMultipleCallback() | ||||
|     { | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     float32 ReportFixture(  b2Fixture* fixture, const b2Vec2& point, | ||||
|         const b2Vec2& normal, float32 fraction) | ||||
|     { | ||||
|         b2Body* body = fixture->GetBody(); | ||||
|         void* userData = body->GetUserData(); | ||||
|         if (userData) | ||||
|         { | ||||
|             int32 index = *(int32*)userData; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 // filter | ||||
|                 return -1.0f; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         b2Assert(m_count < e_maxCount); | ||||
|  | ||||
|         m_points[m_count] = point; | ||||
|         m_normals[m_count] = normal; | ||||
|         ++m_count; | ||||
|  | ||||
|         if (m_count == e_maxCount) | ||||
|         { | ||||
|             return 0.0f; | ||||
|         } | ||||
|  | ||||
|         return 1.0f; | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_points[e_maxCount]; | ||||
|     b2Vec2 m_normals[e_maxCount]; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class RayCast : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_maxBodies = 256 | ||||
|     }; | ||||
|  | ||||
|     enum Mode | ||||
|     { | ||||
|         e_closest, | ||||
|         e_any, | ||||
|         e_multiple | ||||
|     }; | ||||
|  | ||||
|     RayCast() | ||||
|     { | ||||
|         // Ground body | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.5f, 0.0f); | ||||
|             vertices[1].Set(0.5f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[0].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|             vertices[0].Set(-0.1f, 0.0f); | ||||
|             vertices[1].Set(0.1f, 0.0f); | ||||
|             vertices[2].Set(0.0f, 1.5f); | ||||
|             m_polygons[1].Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 w = 1.0f; | ||||
|             float32 b = w / (2.0f + b2Sqrt(2.0f)); | ||||
|             float32 s = b2Sqrt(2.0f) * b; | ||||
|  | ||||
|             b2Vec2 vertices[8]; | ||||
|             vertices[0].Set(0.5f * s, 0.0f); | ||||
|             vertices[1].Set(0.5f * w, b); | ||||
|             vertices[2].Set(0.5f * w, b + s); | ||||
|             vertices[3].Set(0.5f * s, w); | ||||
|             vertices[4].Set(-0.5f * s, w); | ||||
|             vertices[5].Set(-0.5f * w, b + s); | ||||
|             vertices[6].Set(-0.5f * w, b); | ||||
|             vertices[7].Set(-0.5f * s, 0.0f); | ||||
|  | ||||
|             m_polygons[2].Set(vertices, 8); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_polygons[3].SetAsBox(0.5f, 0.5f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_circle.m_radius = 0.5f; | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = 0; | ||||
|         memset(m_bodies, 0, sizeof(m_bodies)); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|  | ||||
|         m_mode = e_closest; | ||||
|     } | ||||
|  | ||||
|     void Create(int32 index) | ||||
|     { | ||||
|         if (m_bodies[m_bodyIndex] != NULL) | ||||
|         { | ||||
|             m_world->DestroyBody(m_bodies[m_bodyIndex]); | ||||
|             m_bodies[m_bodyIndex] = NULL; | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|  | ||||
|         float32 x = RandomFloat(-10.0f, 10.0f); | ||||
|         float32 y = RandomFloat(0.0f, 20.0f); | ||||
|         bd.position.Set(x, y); | ||||
|         bd.angle = RandomFloat(-b2_pi, b2_pi); | ||||
|  | ||||
|         m_userData[m_bodyIndex] = index; | ||||
|         bd.userData = m_userData + m_bodyIndex; | ||||
|  | ||||
|         if (index == 4) | ||||
|         { | ||||
|             bd.angularDamping = 0.02f; | ||||
|         } | ||||
|  | ||||
|         m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | ||||
|  | ||||
|         if (index < 4) | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = m_polygons + index; | ||||
|             fd.friction = 0.3f; | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &m_circle; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             m_bodies[m_bodyIndex]->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | ||||
|     } | ||||
|  | ||||
|     void DestroyBody() | ||||
|     { | ||||
|         for (int32 i = 0; i < e_maxBodies; ++i) | ||||
|         { | ||||
|             if (m_bodies[i] != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bodies[i]); | ||||
|                 m_bodies[i] = NULL; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case '1': | ||||
|         case '2': | ||||
|         case '3': | ||||
|         case '4': | ||||
|         case '5': | ||||
|             Create(key - '1'); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             DestroyBody(); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             if (m_mode == e_closest) | ||||
|             { | ||||
|                 m_mode = e_any; | ||||
|             } | ||||
|             else if (m_mode == e_any) | ||||
|             { | ||||
|                 m_mode = e_multiple; | ||||
|             } | ||||
|             else if (m_mode == e_multiple) | ||||
|             { | ||||
|                 m_mode = e_closest; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         bool advanceRay = settings->pause == 0 || settings->singleStep; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, m to change the mode"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Mode = %d", m_mode); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         float32 L = 11.0f; | ||||
|         b2Vec2 point1(0.0f, 10.0f); | ||||
|         b2Vec2 d(L * cosf(m_angle), L * sinf(m_angle)); | ||||
|         b2Vec2 point2 = point1 + d; | ||||
|  | ||||
|         if (m_mode == e_closest) | ||||
|         { | ||||
|             RayCastClosestCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|             if (callback.m_hit) | ||||
|             { | ||||
|                 m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|                 m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|             } | ||||
|         } | ||||
|         else if (m_mode == e_any) | ||||
|         { | ||||
|             RayCastAnyCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|  | ||||
|             if (callback.m_hit) | ||||
|             { | ||||
|                 m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | ||||
|                 m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|             } | ||||
|         } | ||||
|         else if (m_mode == e_multiple) | ||||
|         { | ||||
|             RayCastMultipleCallback callback; | ||||
|             m_world->RayCast(&callback, point1, point2); | ||||
|             m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|  | ||||
|             for (int32 i = 0; i < callback.m_count; ++i) | ||||
|             { | ||||
|                 b2Vec2 p = callback.m_points[i]; | ||||
|                 b2Vec2 n = callback.m_normals[i]; | ||||
|                 m_debugDraw.DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | ||||
|                 m_debugDraw.DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f)); | ||||
|                 b2Vec2 head = p + 0.5f * n; | ||||
|                 m_debugDraw.DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (advanceRay) | ||||
|         { | ||||
|             m_angle += 0.25f * b2_pi / 180.0f; | ||||
|         } | ||||
|  | ||||
| #if 0 | ||||
|         // This case was failing. | ||||
|         { | ||||
|             b2Vec2 vertices[4]; | ||||
|             //vertices[0].Set(-22.875f, -3.0f); | ||||
|             //vertices[1].Set(22.875f, -3.0f); | ||||
|             //vertices[2].Set(22.875f, 3.0f); | ||||
|             //vertices[3].Set(-22.875f, 3.0f); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             //shape.Set(vertices, 4); | ||||
|             shape.SetAsBox(22.875f, 3.0f); | ||||
|  | ||||
|             b2RayCastInput input; | ||||
|             input.p1.Set(10.2725f,1.71372f); | ||||
|             input.p2.Set(10.2353f,2.21807f); | ||||
|             //input.maxFraction = 0.567623f; | ||||
|             input.maxFraction = 0.56762173f; | ||||
|  | ||||
|             b2Transform xf; | ||||
|             xf.SetIdentity(); | ||||
|             xf.position.Set(23.0f, 5.0f); | ||||
|  | ||||
|             b2RayCastOutput output; | ||||
|             bool hit; | ||||
|             hit = shape.RayCast(&output, input, xf); | ||||
|             hit = false; | ||||
|  | ||||
|             b2Color color(1.0f, 1.0f, 1.0f); | ||||
|             b2Vec2 vs[4]; | ||||
|             for (int32 i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 vs[i] = b2Mul(xf, shape.m_vertices[i]); | ||||
|             } | ||||
|  | ||||
|             m_debugDraw.DrawPolygon(vs, 4, color); | ||||
|             m_debugDraw.DrawSegment(input.p1, input.p2, color); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new RayCast; | ||||
|     } | ||||
|  | ||||
|     int32 m_bodyIndex; | ||||
|     b2Body* m_bodies[e_maxBodies]; | ||||
|     int32 m_userData[e_maxBodies]; | ||||
|     b2PolygonShape m_polygons[4]; | ||||
|     b2CircleShape m_circle; | ||||
|  | ||||
|     float32 m_angle; | ||||
|  | ||||
|     Mode m_mode; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,166 +1,166 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef REVOLUTE_H | ||||
| #define REVOLUTE_H | ||||
|  | ||||
| class Revolute : public Test | ||||
| { | ||||
| public: | ||||
|     Revolute() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             //fd.filter.categoryBits = 2; | ||||
|  | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|  | ||||
|             bd.position.Set(-10.0f, 20.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             float32 w = 100.0f; | ||||
|             body->SetAngularVelocity(w); | ||||
|             body->SetLinearVelocity(b2Vec2(-8.0f * w, 0.0f)); | ||||
|  | ||||
|             rjd.Initialize(ground, body, b2Vec2(-10.0f, 12.0f)); | ||||
|             rjd.motorSpeed = 1.0f * b2_pi; | ||||
|             rjd.maxMotorTorque = 10000.0f; | ||||
|             rjd.enableMotor = false; | ||||
|             rjd.lowerAngle = -0.25f * b2_pi; | ||||
|             rjd.upperAngle = 0.5f * b2_pi; | ||||
|             rjd.enableLimit = true; | ||||
|             rjd.collideConnected = true; | ||||
|  | ||||
|             m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle_shape; | ||||
|             circle_shape.m_radius = 3.0f; | ||||
|  | ||||
|             b2BodyDef circle_bd; | ||||
|             circle_bd.type = b2_dynamicBody; | ||||
|             circle_bd.position.Set(5.0f, 30.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.density = 5.0f; | ||||
|             fd.filter.maskBits = 1; | ||||
|             fd.shape = &circle_shape; | ||||
|  | ||||
|             m_ball = m_world->CreateBody(&circle_bd); | ||||
|             m_ball->CreateFixture(&fd); | ||||
|  | ||||
|             b2PolygonShape polygon_shape; | ||||
|             polygon_shape.SetAsBox(10.0f, 0.2f, b2Vec2 (-10.0f, 0.0f), 0.0f); | ||||
|  | ||||
|             b2BodyDef polygon_bd; | ||||
|             polygon_bd.position.Set(20.0f, 10.0f); | ||||
|             polygon_bd.type = b2_dynamicBody; | ||||
|             polygon_bd.bullet = true; | ||||
|             b2Body* polygon_body = m_world->CreateBody(&polygon_bd); | ||||
|             polygon_body->CreateFixture(&polygon_shape, 2.0f); | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|             rjd.Initialize(ground, polygon_body, b2Vec2(20.0f, 10.0f)); | ||||
|             rjd.lowerAngle = -0.25f * b2_pi; | ||||
|             rjd.upperAngle = 0.0f * b2_pi; | ||||
|             rjd.enableLimit = true; | ||||
|             m_world->CreateJoint(&rjd); | ||||
|         } | ||||
|  | ||||
|         // Tests mass computation of a small object far from the origin | ||||
|         { | ||||
|             b2BodyDef bodyDef; | ||||
|             bodyDef.type = b2_dynamicBody; | ||||
|             b2Body* body = m_world->CreateBody(&bodyDef); | ||||
|  | ||||
|             b2PolygonShape polyShape; | ||||
|             b2Vec2 verts[3]; | ||||
|             verts[0].Set( 17.63f, 36.31f ); | ||||
|             verts[1].Set( 17.52f, 36.69f ); | ||||
|             verts[2].Set( 17.19f, 36.36f ); | ||||
|             polyShape.Set(verts, 3); | ||||
|  | ||||
|             b2FixtureDef polyFixtureDef; | ||||
|             polyFixtureDef.shape = &polyShape; | ||||
|             polyFixtureDef.density = 1; | ||||
|  | ||||
|             body->CreateFixture(&polyFixtureDef);   //assertion hits inside here | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'l': | ||||
|             m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motor"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //if (m_stepCount == 360) | ||||
|         //{ | ||||
|         //  m_ball->SetTransform(b2Vec2(0.0f, 0.5f), 0.0f); | ||||
|         //} | ||||
|  | ||||
|         //float32 torque1 = m_joint1->GetMotorTorque(); | ||||
|         //m_debugDraw.DrawString(5, m_textLine, "Motor Torque = %4.0f, %4.0f : Motor Force = %4.0f", (float) torque1, (float) torque2, (float) force3); | ||||
|         //m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Revolute; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_ball; | ||||
|     b2RevoluteJoint* m_joint; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef REVOLUTE_H | ||||
| #define REVOLUTE_H | ||||
|  | ||||
| class Revolute : public Test | ||||
| { | ||||
| public: | ||||
|     Revolute() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             //fd.filter.categoryBits = 2; | ||||
|  | ||||
|             ground->CreateFixture(&fd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.5f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|  | ||||
|             bd.position.Set(-10.0f, 20.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             float32 w = 100.0f; | ||||
|             body->SetAngularVelocity(w); | ||||
|             body->SetLinearVelocity(b2Vec2(-8.0f * w, 0.0f)); | ||||
|  | ||||
|             rjd.Initialize(ground, body, b2Vec2(-10.0f, 12.0f)); | ||||
|             rjd.motorSpeed = 1.0f * b2_pi; | ||||
|             rjd.maxMotorTorque = 10000.0f; | ||||
|             rjd.enableMotor = false; | ||||
|             rjd.lowerAngle = -0.25f * b2_pi; | ||||
|             rjd.upperAngle = 0.5f * b2_pi; | ||||
|             rjd.enableLimit = true; | ||||
|             rjd.collideConnected = true; | ||||
|  | ||||
|             m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape circle_shape; | ||||
|             circle_shape.m_radius = 3.0f; | ||||
|  | ||||
|             b2BodyDef circle_bd; | ||||
|             circle_bd.type = b2_dynamicBody; | ||||
|             circle_bd.position.Set(5.0f, 30.0f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.density = 5.0f; | ||||
|             fd.filter.maskBits = 1; | ||||
|             fd.shape = &circle_shape; | ||||
|  | ||||
|             m_ball = m_world->CreateBody(&circle_bd); | ||||
|             m_ball->CreateFixture(&fd); | ||||
|  | ||||
|             b2PolygonShape polygon_shape; | ||||
|             polygon_shape.SetAsBox(10.0f, 0.2f, b2Vec2 (-10.0f, 0.0f), 0.0f); | ||||
|  | ||||
|             b2BodyDef polygon_bd; | ||||
|             polygon_bd.position.Set(20.0f, 10.0f); | ||||
|             polygon_bd.type = b2_dynamicBody; | ||||
|             polygon_bd.bullet = true; | ||||
|             b2Body* polygon_body = m_world->CreateBody(&polygon_bd); | ||||
|             polygon_body->CreateFixture(&polygon_shape, 2.0f); | ||||
|  | ||||
|             b2RevoluteJointDef rjd; | ||||
|             rjd.Initialize(ground, polygon_body, b2Vec2(20.0f, 10.0f)); | ||||
|             rjd.lowerAngle = -0.25f * b2_pi; | ||||
|             rjd.upperAngle = 0.0f * b2_pi; | ||||
|             rjd.enableLimit = true; | ||||
|             m_world->CreateJoint(&rjd); | ||||
|         } | ||||
|  | ||||
|         // Tests mass computation of a small object far from the origin | ||||
|         { | ||||
|             b2BodyDef bodyDef; | ||||
|             bodyDef.type = b2_dynamicBody; | ||||
|             b2Body* body = m_world->CreateBody(&bodyDef); | ||||
|  | ||||
|             b2PolygonShape polyShape; | ||||
|             b2Vec2 verts[3]; | ||||
|             verts[0].Set( 17.63f, 36.31f ); | ||||
|             verts[1].Set( 17.52f, 36.69f ); | ||||
|             verts[2].Set( 17.19f, 36.36f ); | ||||
|             polyShape.Set(verts, 3); | ||||
|  | ||||
|             b2FixtureDef polyFixtureDef; | ||||
|             polyFixtureDef.shape = &polyShape; | ||||
|             polyFixtureDef.density = 1; | ||||
|  | ||||
|             body->CreateFixture(&polyFixtureDef);   //assertion hits inside here | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'l': | ||||
|             m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motor"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //if (m_stepCount == 360) | ||||
|         //{ | ||||
|         //  m_ball->SetTransform(b2Vec2(0.0f, 0.5f), 0.0f); | ||||
|         //} | ||||
|  | ||||
|         //float32 torque1 = m_joint1->GetMotorTorque(); | ||||
|         //m_debugDraw.DrawString(5, m_textLine, "Motor Torque = %4.0f, %4.0f : Motor Force = %4.0f", (float) torque1, (float) torque2, (float) force3); | ||||
|         //m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Revolute; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_ball; | ||||
|     b2RevoluteJoint* m_joint; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,101 +1,101 @@ | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ROPE_H | ||||
| #define ROPE_H | ||||
|  | ||||
| /// | ||||
| class Rope : public Test | ||||
| { | ||||
| public: | ||||
|     Rope() | ||||
|     { | ||||
|         const int32 N = 40; | ||||
|         b2Vec2 vertices[N]; | ||||
|         float32 masses[N]; | ||||
|  | ||||
|         for (int32 i = 0; i < N; ++i) | ||||
|         { | ||||
|             vertices[i].Set(0.0f, 20.0f - 0.25f * i); | ||||
|             masses[i] = 1.0f; | ||||
|         } | ||||
|         masses[0] = 0.0f; | ||||
|         masses[1] = 0.0f; | ||||
|  | ||||
|         b2RopeDef def; | ||||
|         def.vertices = vertices; | ||||
|         def.count = N; | ||||
|         def.gravity.Set(0.0f, -10.0f); | ||||
|         def.masses = masses; | ||||
|         def.damping = 0.1f; | ||||
|         def.k2 = 1.0f; | ||||
|         def.k3 = 0.5f; | ||||
|  | ||||
|         m_rope.Initialize(&def); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|         m_rope.SetAngle(m_angle); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'q': | ||||
|             m_angle = b2Max(-b2_pi, m_angle - 0.05f * b2_pi); | ||||
|             m_rope.SetAngle(m_angle); | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angle = b2Min(b2_pi, m_angle + 0.05f * b2_pi); | ||||
|             m_rope.SetAngle(m_angle); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         float32 dt = settings->hz > 0.0f ? 1.0f / settings->hz : 0.0f; | ||||
|  | ||||
|         if (settings->pause == 1 && settings->singleStep == 0) | ||||
|         { | ||||
|             dt = 0.0f; | ||||
|         } | ||||
|  | ||||
|         m_rope.Step(dt, 1); | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         m_rope.Draw(&m_debugDraw); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press (q,e) to adjust target angle"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Target angle = %g degrees", m_angle * 180.0f / b2_pi); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Rope; | ||||
|     } | ||||
|  | ||||
|     b2Rope m_rope; | ||||
|     float32 m_angle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ROPE_H | ||||
| #define ROPE_H | ||||
|  | ||||
| /// | ||||
| class Rope : public Test | ||||
| { | ||||
| public: | ||||
|     Rope() | ||||
|     { | ||||
|         const int32 N = 40; | ||||
|         b2Vec2 vertices[N]; | ||||
|         float32 masses[N]; | ||||
|  | ||||
|         for (int32 i = 0; i < N; ++i) | ||||
|         { | ||||
|             vertices[i].Set(0.0f, 20.0f - 0.25f * i); | ||||
|             masses[i] = 1.0f; | ||||
|         } | ||||
|         masses[0] = 0.0f; | ||||
|         masses[1] = 0.0f; | ||||
|  | ||||
|         b2RopeDef def; | ||||
|         def.vertices = vertices; | ||||
|         def.count = N; | ||||
|         def.gravity.Set(0.0f, -10.0f); | ||||
|         def.masses = masses; | ||||
|         def.damping = 0.1f; | ||||
|         def.k2 = 1.0f; | ||||
|         def.k3 = 0.5f; | ||||
|  | ||||
|         m_rope.Initialize(&def); | ||||
|  | ||||
|         m_angle = 0.0f; | ||||
|         m_rope.SetAngle(m_angle); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'q': | ||||
|             m_angle = b2Max(-b2_pi, m_angle - 0.05f * b2_pi); | ||||
|             m_rope.SetAngle(m_angle); | ||||
|             break; | ||||
|  | ||||
|         case 'e': | ||||
|             m_angle = b2Min(b2_pi, m_angle + 0.05f * b2_pi); | ||||
|             m_rope.SetAngle(m_angle); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         float32 dt = settings->hz > 0.0f ? 1.0f / settings->hz : 0.0f; | ||||
|  | ||||
|         if (settings->pause == 1 && settings->singleStep == 0) | ||||
|         { | ||||
|             dt = 0.0f; | ||||
|         } | ||||
|  | ||||
|         m_rope.Step(dt, 1); | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         m_rope.Draw(&m_debugDraw); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press (q,e) to adjust target angle"); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Target angle = %g degrees", m_angle * 180.0f / b2_pi); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Rope; | ||||
|     } | ||||
|  | ||||
|     b2Rope m_rope; | ||||
|     float32 m_angle; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,145 +1,145 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ROPE_JOINT_H | ||||
| #define ROPE_JOINT_H | ||||
|  | ||||
| /// This test shows how a rope joint can be used to stabilize a chain of | ||||
| /// bodies with a heavy payload. Notice that the rope joint just prevents | ||||
| /// excessive stretching and has no other effect. | ||||
| /// By disabling the rope joint you can see that the Box2D solver has trouble | ||||
| /// supporting heavy bodies with light bodies. Try playing around with the | ||||
| /// densities, time step, and iterations to see how they affect stability. | ||||
| /// This test also shows how to use contact filtering. Filtering is configured | ||||
| /// so that the payload does not collide with the chain. | ||||
| class RopeJoint : public Test | ||||
| { | ||||
| public: | ||||
|     RopeJoint() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|             fd.filter.categoryBits = 0x0001; | ||||
|             fd.filter.maskBits = 0xFFFF & ~0x0002; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.collideConnected = false; | ||||
|  | ||||
|             const int32 N = 10; | ||||
|             const float32 y = 15.0f; | ||||
|             m_ropeDef.localAnchorA.Set(0.0f, y); | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.5f + 1.0f * i, y); | ||||
|                 if (i == N - 1) | ||||
|                 { | ||||
|                     shape.SetAsBox(1.5f, 1.5f); | ||||
|                     fd.density = 100.0f; | ||||
|                     fd.filter.categoryBits = 0x0002; | ||||
|                     bd.position.Set(1.0f * i, y); | ||||
|                     bd.angularDamping = 0.4f; | ||||
|                 } | ||||
|  | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(float32(i), y); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             m_ropeDef.localAnchorB.SetZero(); | ||||
|  | ||||
|             float32 extraLength = 0.01f; | ||||
|             m_ropeDef.maxLength = N - 1.0f + extraLength; | ||||
|             m_ropeDef.bodyB = prevBody; | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_ropeDef.bodyA = ground; | ||||
|             m_rope = m_world->CreateJoint(&m_ropeDef); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'j': | ||||
|             if (m_rope) | ||||
|             { | ||||
|                 m_world->DestroyJoint(m_rope); | ||||
|                 m_rope = NULL; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_rope = m_world->CreateJoint(&m_ropeDef); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press (j) to toggle the rope joint."); | ||||
|         m_textLine += 15; | ||||
|         if (m_rope) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "Rope ON"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "Rope OFF"); | ||||
|         } | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new RopeJoint; | ||||
|     } | ||||
|  | ||||
|     b2RopeJointDef m_ropeDef; | ||||
|     b2Joint* m_rope; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef ROPE_JOINT_H | ||||
| #define ROPE_JOINT_H | ||||
|  | ||||
| /// This test shows how a rope joint can be used to stabilize a chain of | ||||
| /// bodies with a heavy payload. Notice that the rope joint just prevents | ||||
| /// excessive stretching and has no other effect. | ||||
| /// By disabling the rope joint you can see that the Box2D solver has trouble | ||||
| /// supporting heavy bodies with light bodies. Try playing around with the | ||||
| /// densities, time step, and iterations to see how they affect stability. | ||||
| /// This test also shows how to use contact filtering. Filtering is configured | ||||
| /// so that the payload does not collide with the chain. | ||||
| class RopeJoint : public Test | ||||
| { | ||||
| public: | ||||
|     RopeJoint() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.125f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 20.0f; | ||||
|             fd.friction = 0.2f; | ||||
|             fd.filter.categoryBits = 0x0001; | ||||
|             fd.filter.maskBits = 0xFFFF & ~0x0002; | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.collideConnected = false; | ||||
|  | ||||
|             const int32 N = 10; | ||||
|             const float32 y = 15.0f; | ||||
|             m_ropeDef.localAnchorA.Set(0.0f, y); | ||||
|  | ||||
|             b2Body* prevBody = ground; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.5f + 1.0f * i, y); | ||||
|                 if (i == N - 1) | ||||
|                 { | ||||
|                     shape.SetAsBox(1.5f, 1.5f); | ||||
|                     fd.density = 100.0f; | ||||
|                     fd.filter.categoryBits = 0x0002; | ||||
|                     bd.position.Set(1.0f * i, y); | ||||
|                     bd.angularDamping = 0.4f; | ||||
|                 } | ||||
|  | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|  | ||||
|                 b2Vec2 anchor(float32(i), y); | ||||
|                 jd.Initialize(prevBody, body, anchor); | ||||
|                 m_world->CreateJoint(&jd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             m_ropeDef.localAnchorB.SetZero(); | ||||
|  | ||||
|             float32 extraLength = 0.01f; | ||||
|             m_ropeDef.maxLength = N - 1.0f + extraLength; | ||||
|             m_ropeDef.bodyB = prevBody; | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             m_ropeDef.bodyA = ground; | ||||
|             m_rope = m_world->CreateJoint(&m_ropeDef); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'j': | ||||
|             if (m_rope) | ||||
|             { | ||||
|                 m_world->DestroyJoint(m_rope); | ||||
|                 m_rope = NULL; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_rope = m_world->CreateJoint(&m_ropeDef); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press (j) to toggle the rope joint."); | ||||
|         m_textLine += 15; | ||||
|         if (m_rope) | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "Rope ON"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_debugDraw.DrawString(5, m_textLine, "Rope OFF"); | ||||
|         } | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new RopeJoint; | ||||
|     } | ||||
|  | ||||
|     b2RopeJointDef m_ropeDef; | ||||
|     b2Joint* m_rope; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,181 +1,181 @@ | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SENSOR_TEST_H | ||||
| #define SENSOR_TEST_H | ||||
|  | ||||
| // This is used to test sensor shapes. | ||||
| class SensorTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 7 | ||||
|     }; | ||||
|  | ||||
|     SensorTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             { | ||||
|                 b2EdgeShape shape; | ||||
|                 shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|                 ground->CreateFixture(&shape, 0.0f); | ||||
|             } | ||||
|  | ||||
| #if 0 | ||||
|             { | ||||
|                 b2FixtureDef sd; | ||||
|                 sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f); | ||||
|                 sd.isSensor = true; | ||||
|                 m_sensor = ground->CreateFixture(&sd); | ||||
|             } | ||||
| #else | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 5.0f; | ||||
|                 shape.m_p.Set(0.0f, 10.0f); | ||||
|  | ||||
|                 b2FixtureDef fd; | ||||
|                 fd.shape = &shape; | ||||
|                 fd.isSensor = true; | ||||
|                 m_sensor = ground->CreateFixture(&fd); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + 3.0f * i, 20.0f); | ||||
|                 bd.userData = m_touching + i; | ||||
|  | ||||
|                 m_touching[i] = false; | ||||
|                 m_bodies[i] = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[i]->CreateFixture(&shape, 1.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Implement contact listener. | ||||
|     void BeginContact(b2Contact* contact) | ||||
|     { | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureB->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (fixtureB == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureA->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Implement contact listener. | ||||
|     void EndContact(b2Contact* contact) | ||||
|     { | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureB->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (fixtureB == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureA->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         // Traverse the contact results. Apply a force on shapes | ||||
|         // that overlap the sensor. | ||||
|         for (int32 i = 0; i < e_count; ++i) | ||||
|         { | ||||
|             if (m_touching[i] == false) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2Body* body = m_bodies[i]; | ||||
|             b2Body* ground = m_sensor->GetBody(); | ||||
|  | ||||
|             b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape(); | ||||
|             b2Vec2 center = ground->GetWorldPoint(circle->m_p); | ||||
|  | ||||
|             b2Vec2 position = body->GetPosition(); | ||||
|  | ||||
|             b2Vec2 d = center - position; | ||||
|             if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             d.Normalize(); | ||||
|             b2Vec2 F = 100.0f * d; | ||||
|             body->ApplyForce(F, position); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SensorTest; | ||||
|     } | ||||
|  | ||||
|     b2Fixture* m_sensor; | ||||
|     b2Body* m_bodies[e_count]; | ||||
|     bool m_touching[e_count]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SENSOR_TEST_H | ||||
| #define SENSOR_TEST_H | ||||
|  | ||||
| // This is used to test sensor shapes. | ||||
| class SensorTest : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 7 | ||||
|     }; | ||||
|  | ||||
|     SensorTest() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             { | ||||
|                 b2EdgeShape shape; | ||||
|                 shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|                 ground->CreateFixture(&shape, 0.0f); | ||||
|             } | ||||
|  | ||||
| #if 0 | ||||
|             { | ||||
|                 b2FixtureDef sd; | ||||
|                 sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f); | ||||
|                 sd.isSensor = true; | ||||
|                 m_sensor = ground->CreateFixture(&sd); | ||||
|             } | ||||
| #else | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 5.0f; | ||||
|                 shape.m_p.Set(0.0f, 10.0f); | ||||
|  | ||||
|                 b2FixtureDef fd; | ||||
|                 fd.shape = &shape; | ||||
|                 fd.isSensor = true; | ||||
|                 m_sensor = ground->CreateFixture(&fd); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + 3.0f * i, 20.0f); | ||||
|                 bd.userData = m_touching + i; | ||||
|  | ||||
|                 m_touching[i] = false; | ||||
|                 m_bodies[i] = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[i]->CreateFixture(&shape, 1.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Implement contact listener. | ||||
|     void BeginContact(b2Contact* contact) | ||||
|     { | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureB->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (fixtureB == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureA->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Implement contact listener. | ||||
|     void EndContact(b2Contact* contact) | ||||
|     { | ||||
|         b2Fixture* fixtureA = contact->GetFixtureA(); | ||||
|         b2Fixture* fixtureB = contact->GetFixtureB(); | ||||
|  | ||||
|         if (fixtureA == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureB->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (fixtureB == m_sensor) | ||||
|         { | ||||
|             void* userData = fixtureA->GetBody()->GetUserData(); | ||||
|             if (userData) | ||||
|             { | ||||
|                 bool* touching = (bool*)userData; | ||||
|                 *touching = false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         // Traverse the contact results. Apply a force on shapes | ||||
|         // that overlap the sensor. | ||||
|         for (int32 i = 0; i < e_count; ++i) | ||||
|         { | ||||
|             if (m_touching[i] == false) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             b2Body* body = m_bodies[i]; | ||||
|             b2Body* ground = m_sensor->GetBody(); | ||||
|  | ||||
|             b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape(); | ||||
|             b2Vec2 center = ground->GetWorldPoint(circle->m_p); | ||||
|  | ||||
|             b2Vec2 position = body->GetPosition(); | ||||
|  | ||||
|             b2Vec2 d = center - position; | ||||
|             if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             d.Normalize(); | ||||
|             b2Vec2 F = 100.0f * d; | ||||
|             body->ApplyForce(F, position); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SensorTest; | ||||
|     } | ||||
|  | ||||
|     b2Fixture* m_sensor; | ||||
|     b2Body* m_bodies[e_count]; | ||||
|     bool m_touching[e_count]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,105 +1,105 @@ | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SHAPE_EDITING_H | ||||
| #define SHAPE_EDITING_H | ||||
|  | ||||
| class ShapeEditing : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     ShapeEditing() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position.Set(0.0f, 10.0f); | ||||
|         m_body = m_world->CreateBody(&bd); | ||||
|  | ||||
|         b2PolygonShape shape; | ||||
|         shape.SetAsBox(4.0f, 4.0f, b2Vec2(0.0f, 0.0f), 0.0f); | ||||
|         m_fixture1 = m_body->CreateFixture(&shape, 10.0f); | ||||
|  | ||||
|         m_fixture2 = NULL; | ||||
|  | ||||
|         m_sensor = false; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'c': | ||||
|             if (m_fixture2 == NULL) | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 3.0f; | ||||
|                 shape.m_p.Set(0.5f, -4.0f); | ||||
|                 m_fixture2 = m_body->CreateFixture(&shape, 10.0f); | ||||
|                 m_body->SetAwake(true); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             if (m_fixture2 != NULL) | ||||
|             { | ||||
|                 m_body->DestroyFixture(m_fixture2); | ||||
|                 m_fixture2 = NULL; | ||||
|                 m_body->SetAwake(true); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             if (m_fixture2 != NULL) | ||||
|             { | ||||
|                 m_sensor = !m_sensor; | ||||
|                 m_fixture2->SetSensor(m_sensor); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "sensor = %d", m_sensor); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ShapeEditing; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     b2Fixture* m_fixture1; | ||||
|     b2Fixture* m_fixture2; | ||||
|     bool m_sensor; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SHAPE_EDITING_H | ||||
| #define SHAPE_EDITING_H | ||||
|  | ||||
| class ShapeEditing : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     ShapeEditing() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         b2BodyDef bd; | ||||
|         bd.type = b2_dynamicBody; | ||||
|         bd.position.Set(0.0f, 10.0f); | ||||
|         m_body = m_world->CreateBody(&bd); | ||||
|  | ||||
|         b2PolygonShape shape; | ||||
|         shape.SetAsBox(4.0f, 4.0f, b2Vec2(0.0f, 0.0f), 0.0f); | ||||
|         m_fixture1 = m_body->CreateFixture(&shape, 10.0f); | ||||
|  | ||||
|         m_fixture2 = NULL; | ||||
|  | ||||
|         m_sensor = false; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'c': | ||||
|             if (m_fixture2 == NULL) | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 3.0f; | ||||
|                 shape.m_p.Set(0.5f, -4.0f); | ||||
|                 m_fixture2 = m_body->CreateFixture(&shape, 10.0f); | ||||
|                 m_body->SetAwake(true); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             if (m_fixture2 != NULL) | ||||
|             { | ||||
|                 m_body->DestroyFixture(m_fixture2); | ||||
|                 m_fixture2 = NULL; | ||||
|                 m_body->SetAwake(true); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             if (m_fixture2 != NULL) | ||||
|             { | ||||
|                 m_sensor = !m_sensor; | ||||
|                 m_fixture2->SetSensor(m_sensor); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "sensor = %d", m_sensor); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new ShapeEditing; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_body; | ||||
|     b2Fixture* m_fixture1; | ||||
|     b2Fixture* m_fixture2; | ||||
|     bool m_sensor; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,156 +1,156 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SLIDER_CRANK_H | ||||
| #define SLIDER_CRANK_H | ||||
|  | ||||
| // A motor driven slider crank with joint friction. | ||||
|  | ||||
| class SliderCrank : public Test | ||||
| { | ||||
| public: | ||||
|     SliderCrank() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Body* prevBody = ground; | ||||
|  | ||||
|             // Define crank. | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(0.5f, 2.0f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 7.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 5.0f)); | ||||
|                 rjd.motorSpeed = 1.0f * b2_pi; | ||||
|                 rjd.maxMotorTorque = 10000.0f; | ||||
|                 rjd.enableMotor = true; | ||||
|                 m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             // Define follower. | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(0.5f, 4.0f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 13.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 9.0f)); | ||||
|                 rjd.enableMotor = false; | ||||
|                 m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             // Define piston | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(1.5f, 1.5f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.fixedRotation = true; | ||||
|                 bd.position.Set(0.0f, 17.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 17.0f)); | ||||
|                 m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 b2PrismaticJointDef pjd; | ||||
|                 pjd.Initialize(ground, body, b2Vec2(0.0f, 17.0f), b2Vec2(0.0f, 1.0f)); | ||||
|  | ||||
|                 pjd.maxMotorForce = 1000.0f; | ||||
|                 pjd.enableMotor = true; | ||||
|  | ||||
|                 m_joint2 = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); | ||||
|             } | ||||
|  | ||||
|             // Create a payload | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(1.5f, 1.5f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 23.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'f': | ||||
|             m_joint2->EnableMotor(!m_joint2->IsMotorEnabled()); | ||||
|             m_joint2->GetBodyB()->SetAwake(true); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint1->EnableMotor(!m_joint1->IsMotorEnabled()); | ||||
|             m_joint1->GetBodyB()->SetAwake(true); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (f) toggle friction, (m) toggle motor"); | ||||
|         m_textLine += 15; | ||||
|         float32 torque = m_joint1->GetMotorTorque(settings->hz); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Motor Torque = %5.0f", (float) torque); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SliderCrank; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint1; | ||||
|     b2PrismaticJoint* m_joint2; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SLIDER_CRANK_H | ||||
| #define SLIDER_CRANK_H | ||||
|  | ||||
| // A motor driven slider crank with joint friction. | ||||
|  | ||||
| class SliderCrank : public Test | ||||
| { | ||||
| public: | ||||
|     SliderCrank() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2Body* prevBody = ground; | ||||
|  | ||||
|             // Define crank. | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(0.5f, 2.0f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 7.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 5.0f)); | ||||
|                 rjd.motorSpeed = 1.0f * b2_pi; | ||||
|                 rjd.maxMotorTorque = 10000.0f; | ||||
|                 rjd.enableMotor = true; | ||||
|                 m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             // Define follower. | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(0.5f, 4.0f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 13.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 9.0f)); | ||||
|                 rjd.enableMotor = false; | ||||
|                 m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 prevBody = body; | ||||
|             } | ||||
|  | ||||
|             // Define piston | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(1.5f, 1.5f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.fixedRotation = true; | ||||
|                 bd.position.Set(0.0f, 17.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|  | ||||
|                 b2RevoluteJointDef rjd; | ||||
|                 rjd.Initialize(prevBody, body, b2Vec2(0.0f, 17.0f)); | ||||
|                 m_world->CreateJoint(&rjd); | ||||
|  | ||||
|                 b2PrismaticJointDef pjd; | ||||
|                 pjd.Initialize(ground, body, b2Vec2(0.0f, 17.0f), b2Vec2(0.0f, 1.0f)); | ||||
|  | ||||
|                 pjd.maxMotorForce = 1000.0f; | ||||
|                 pjd.enableMotor = true; | ||||
|  | ||||
|                 m_joint2 = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); | ||||
|             } | ||||
|  | ||||
|             // Create a payload | ||||
|             { | ||||
|                 b2PolygonShape shape; | ||||
|                 shape.SetAsBox(1.5f, 1.5f); | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0f, 23.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|                 body->CreateFixture(&shape, 2.0f); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'f': | ||||
|             m_joint2->EnableMotor(!m_joint2->IsMotorEnabled()); | ||||
|             m_joint2->GetBodyB()->SetAwake(true); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_joint1->EnableMotor(!m_joint1->IsMotorEnabled()); | ||||
|             m_joint1->GetBodyB()->SetAwake(true); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: (f) toggle friction, (m) toggle motor"); | ||||
|         m_textLine += 15; | ||||
|         float32 torque = m_joint1->GetMotorTorque(settings->hz); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Motor Torque = %5.0f", (float) torque); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SliderCrank; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint1; | ||||
|     b2PrismaticJoint* m_joint2; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,86 +1,86 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_STACK_H | ||||
| #define SPHERE_STACK_H | ||||
|  | ||||
| class SphereStack : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 10 | ||||
|     }; | ||||
|  | ||||
|     SphereStack() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0, 4.0f + 3.0f * i); | ||||
|  | ||||
|                 m_bodies[i] = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[i]->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|                 m_bodies[i]->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         //for (int32 i = 0; i < e_count; ++i) | ||||
|         //{ | ||||
|         //  printf("%g ", m_bodies[i]->GetWorldCenter().y); | ||||
|         //} | ||||
|  | ||||
|         //for (int32 i = 0; i < e_count; ++i) | ||||
|         //{ | ||||
|         //  printf("%g ", m_bodies[i]->GetLinearVelocity().y); | ||||
|         //} | ||||
|  | ||||
|         //printf("\n"); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SphereStack; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bodies[e_count]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef SPHERE_STACK_H | ||||
| #define SPHERE_STACK_H | ||||
|  | ||||
| class SphereStack : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 10 | ||||
|     }; | ||||
|  | ||||
|     SphereStack() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(0.0, 4.0f + 3.0f * i); | ||||
|  | ||||
|                 m_bodies[i] = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[i]->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|                 m_bodies[i]->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         //for (int32 i = 0; i < e_count; ++i) | ||||
|         //{ | ||||
|         //  printf("%g ", m_bodies[i]->GetWorldCenter().y); | ||||
|         //} | ||||
|  | ||||
|         //for (int32 i = 0; i < e_count; ++i) | ||||
|         //{ | ||||
|         //  printf("%g ", m_bodies[i]->GetLinearVelocity().y); | ||||
|         //} | ||||
|  | ||||
|         //printf("\n"); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new SphereStack; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bodies[e_count]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,125 +1,125 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "../Framework/Test.h" | ||||
| #include "../Framework/Render.h" | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|     #include <GLUT/glut.h> | ||||
| #else | ||||
|     #include "freeglut/freeglut.h" | ||||
| #endif | ||||
|  | ||||
| #include <cstring> | ||||
| using namespace std; | ||||
|  | ||||
| #include "AddPair.h" | ||||
| #include "ApplyForce.h" | ||||
| #include "BodyTypes.h" | ||||
| #include "Breakable.h" | ||||
| #include "Bridge.h" | ||||
| #include "BulletTest.h" | ||||
| #include "Cantilever.h" | ||||
| #include "Car.h" | ||||
| #include "ContinuousTest.h" | ||||
| #include "Chain.h" | ||||
| #include "CharacterCollision.h" | ||||
| #include "CollisionFiltering.h" | ||||
| #include "CollisionProcessing.h" | ||||
| #include "CompoundShapes.h" | ||||
| #include "Confined.h" | ||||
| #include "DistanceTest.h" | ||||
| #include "Dominos.h" | ||||
| #include "DumpShell.h" | ||||
| #include "DynamicTreeTest.h" | ||||
| #include "EdgeShapes.h" | ||||
| #include "EdgeTest.h" | ||||
| #include "Gears.h" | ||||
| #include "OneSidedPlatform.h" | ||||
| #include "Pinball.h" | ||||
| #include "PolyCollision.h" | ||||
| #include "PolyShapes.h" | ||||
| #include "Prismatic.h" | ||||
| #include "Pulleys.h" | ||||
| #include "Pyramid.h" | ||||
| #include "RayCast.h" | ||||
| #include "Revolute.h" | ||||
| //#include "Rope.h" | ||||
| #include "RopeJoint.h" | ||||
| #include "SensorTest.h" | ||||
| #include "ShapeEditing.h" | ||||
| #include "SliderCrank.h" | ||||
| #include "SphereStack.h" | ||||
| #include "TheoJansen.h" | ||||
| #include "Tiles.h" | ||||
| #include "TimeOfImpact.h" | ||||
| #include "Tumbler.h" | ||||
| #include "VaryingFriction.h" | ||||
| #include "VaryingRestitution.h" | ||||
| #include "VerticalStack.h" | ||||
| #include "Web.h" | ||||
|  | ||||
| TestEntry g_testEntries[] = | ||||
| { | ||||
|     {"Tumbler", Tumbler::Create}, | ||||
|     {"Tiles", Tiles::Create}, | ||||
|     {"Dump Shell", DumpShell::Create}, | ||||
|     {"Gears", Gears::Create}, | ||||
|     {"Cantilever", Cantilever::Create}, | ||||
|     {"Varying Restitution", VaryingRestitution::Create}, | ||||
|     {"Character Collision", CharacterCollision::Create}, | ||||
|     {"Edge Test", EdgeTest::Create}, | ||||
|     {"Body Types", BodyTypes::Create}, | ||||
|     {"Shape Editing", ShapeEditing::Create}, | ||||
|     {"Car", Car::Create}, | ||||
|     {"Apply Force", ApplyForce::Create}, | ||||
|     {"Prismatic", Prismatic::Create}, | ||||
|     {"Vertical Stack", VerticalStack::Create}, | ||||
|     {"SphereStack", SphereStack::Create}, | ||||
|     {"Revolute", Revolute::Create}, | ||||
|     {"Pulleys", Pulleys::Create}, | ||||
|     {"Polygon Shapes", PolyShapes::Create}, | ||||
|     //{"Rope", Rope::Create}, | ||||
|     {"Web", Web::Create}, | ||||
|     {"RopeJoint", RopeJoint::Create}, | ||||
|     {"One-Sided Platform", OneSidedPlatform::Create}, | ||||
|     {"Pinball", Pinball::Create}, | ||||
|     {"Bullet Test", BulletTest::Create}, | ||||
|     {"Continuous Test", ContinuousTest::Create}, | ||||
|     {"Time of Impact", TimeOfImpact::Create}, | ||||
|     {"Ray-Cast", RayCast::Create}, | ||||
|     {"Confined", Confined::Create}, | ||||
|     {"Pyramid", Pyramid::Create}, | ||||
|     {"Theo Jansen's Walker", TheoJansen::Create}, | ||||
|     {"Edge Shapes", EdgeShapes::Create}, | ||||
|     {"PolyCollision", PolyCollision::Create}, | ||||
|     {"Bridge", Bridge::Create}, | ||||
|     {"Breakable", Breakable::Create}, | ||||
|     {"Chain", Chain::Create}, | ||||
|     {"Collision Filtering", CollisionFiltering::Create}, | ||||
|     {"Collision Processing", CollisionProcessing::Create}, | ||||
|     {"Compound Shapes", CompoundShapes::Create}, | ||||
|     {"Distance Test", DistanceTest::Create}, | ||||
|     {"Dominos", Dominos::Create}, | ||||
|     {"Dynamic Tree", DynamicTreeTest::Create}, | ||||
|     {"Sensor Test", SensorTest::Create}, | ||||
|     {"Slider Crank", SliderCrank::Create}, | ||||
|     {"Varying Friction", VaryingFriction::Create}, | ||||
|     {"Add Pair Stress Test", AddPair::Create}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #include "../Framework/Test.h" | ||||
| #include "../Framework/Render.h" | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|     #include <GLUT/glut.h> | ||||
| #else | ||||
|     #include "freeglut/freeglut.h" | ||||
| #endif | ||||
|  | ||||
| #include <cstring> | ||||
| using namespace std; | ||||
|  | ||||
| #include "AddPair.h" | ||||
| #include "ApplyForce.h" | ||||
| #include "BodyTypes.h" | ||||
| #include "Breakable.h" | ||||
| #include "Bridge.h" | ||||
| #include "BulletTest.h" | ||||
| #include "Cantilever.h" | ||||
| #include "Car.h" | ||||
| #include "ContinuousTest.h" | ||||
| #include "Chain.h" | ||||
| #include "CharacterCollision.h" | ||||
| #include "CollisionFiltering.h" | ||||
| #include "CollisionProcessing.h" | ||||
| #include "CompoundShapes.h" | ||||
| #include "Confined.h" | ||||
| #include "DistanceTest.h" | ||||
| #include "Dominos.h" | ||||
| #include "DumpShell.h" | ||||
| #include "DynamicTreeTest.h" | ||||
| #include "EdgeShapes.h" | ||||
| #include "EdgeTest.h" | ||||
| #include "Gears.h" | ||||
| #include "OneSidedPlatform.h" | ||||
| #include "Pinball.h" | ||||
| #include "PolyCollision.h" | ||||
| #include "PolyShapes.h" | ||||
| #include "Prismatic.h" | ||||
| #include "Pulleys.h" | ||||
| #include "Pyramid.h" | ||||
| #include "RayCast.h" | ||||
| #include "Revolute.h" | ||||
| //#include "Rope.h" | ||||
| #include "RopeJoint.h" | ||||
| #include "SensorTest.h" | ||||
| #include "ShapeEditing.h" | ||||
| #include "SliderCrank.h" | ||||
| #include "SphereStack.h" | ||||
| #include "TheoJansen.h" | ||||
| #include "Tiles.h" | ||||
| #include "TimeOfImpact.h" | ||||
| #include "Tumbler.h" | ||||
| #include "VaryingFriction.h" | ||||
| #include "VaryingRestitution.h" | ||||
| #include "VerticalStack.h" | ||||
| #include "Web.h" | ||||
|  | ||||
| TestEntry g_testEntries[] = | ||||
| { | ||||
|     {"Tumbler", Tumbler::Create}, | ||||
|     {"Tiles", Tiles::Create}, | ||||
|     {"Dump Shell", DumpShell::Create}, | ||||
|     {"Gears", Gears::Create}, | ||||
|     {"Cantilever", Cantilever::Create}, | ||||
|     {"Varying Restitution", VaryingRestitution::Create}, | ||||
|     {"Character Collision", CharacterCollision::Create}, | ||||
|     {"Edge Test", EdgeTest::Create}, | ||||
|     {"Body Types", BodyTypes::Create}, | ||||
|     {"Shape Editing", ShapeEditing::Create}, | ||||
|     {"Car", Car::Create}, | ||||
|     {"Apply Force", ApplyForce::Create}, | ||||
|     {"Prismatic", Prismatic::Create}, | ||||
|     {"Vertical Stack", VerticalStack::Create}, | ||||
|     {"SphereStack", SphereStack::Create}, | ||||
|     {"Revolute", Revolute::Create}, | ||||
|     {"Pulleys", Pulleys::Create}, | ||||
|     {"Polygon Shapes", PolyShapes::Create}, | ||||
|     //{"Rope", Rope::Create}, | ||||
|     {"Web", Web::Create}, | ||||
|     {"RopeJoint", RopeJoint::Create}, | ||||
|     {"One-Sided Platform", OneSidedPlatform::Create}, | ||||
|     {"Pinball", Pinball::Create}, | ||||
|     {"Bullet Test", BulletTest::Create}, | ||||
|     {"Continuous Test", ContinuousTest::Create}, | ||||
|     {"Time of Impact", TimeOfImpact::Create}, | ||||
|     {"Ray-Cast", RayCast::Create}, | ||||
|     {"Confined", Confined::Create}, | ||||
|     {"Pyramid", Pyramid::Create}, | ||||
|     {"Theo Jansen's Walker", TheoJansen::Create}, | ||||
|     {"Edge Shapes", EdgeShapes::Create}, | ||||
|     {"PolyCollision", PolyCollision::Create}, | ||||
|     {"Bridge", Bridge::Create}, | ||||
|     {"Breakable", Breakable::Create}, | ||||
|     {"Chain", Chain::Create}, | ||||
|     {"Collision Filtering", CollisionFiltering::Create}, | ||||
|     {"Collision Processing", CollisionProcessing::Create}, | ||||
|     {"Compound Shapes", CompoundShapes::Create}, | ||||
|     {"Distance Test", DistanceTest::Create}, | ||||
|     {"Dominos", Dominos::Create}, | ||||
|     {"Dynamic Tree", DynamicTreeTest::Create}, | ||||
|     {"Sensor Test", SensorTest::Create}, | ||||
|     {"Slider Crank", SliderCrank::Create}, | ||||
|     {"Varying Friction", VaryingFriction::Create}, | ||||
|     {"Add Pair Stress Test", AddPair::Create}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
|   | ||||
| @@ -1,256 +1,256 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| // Inspired by a contribution by roman_m | ||||
| // Dimensions scooped from APE (http://www.cove.org/ape/index.htm) | ||||
|  | ||||
| #ifndef THEO_JANSEN_H | ||||
| #define THEO_JANSEN_H | ||||
|  | ||||
| class TheoJansen : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     void CreateLeg(float32 s, const b2Vec2& wheelAnchor) | ||||
|     { | ||||
|         b2Vec2 p1(5.4f * s, -6.1f); | ||||
|         b2Vec2 p2(7.2f * s, -1.2f); | ||||
|         b2Vec2 p3(4.3f * s, -1.9f); | ||||
|         b2Vec2 p4(3.1f * s, 0.8f); | ||||
|         b2Vec2 p5(6.0f * s, 1.5f); | ||||
|         b2Vec2 p6(2.5f * s, 3.7f); | ||||
|  | ||||
|         b2FixtureDef fd1, fd2; | ||||
|         fd1.filter.groupIndex = -1; | ||||
|         fd2.filter.groupIndex = -1; | ||||
|         fd1.density = 1.0f; | ||||
|         fd2.density = 1.0f; | ||||
|  | ||||
|         b2PolygonShape poly1, poly2; | ||||
|  | ||||
|         if (s > 0.0f) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             vertices[0] = p1; | ||||
|             vertices[1] = p2; | ||||
|             vertices[2] = p3; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             vertices[0] = b2Vec2_zero; | ||||
|             vertices[1] = p5 - p4; | ||||
|             vertices[2] = p6 - p4; | ||||
|             poly2.Set(vertices, 3); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             vertices[0] = p1; | ||||
|             vertices[1] = p3; | ||||
|             vertices[2] = p2; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             vertices[0] = b2Vec2_zero; | ||||
|             vertices[1] = p6 - p4; | ||||
|             vertices[2] = p5 - p4; | ||||
|             poly2.Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         fd1.shape = &poly1; | ||||
|         fd2.shape = &poly2; | ||||
|  | ||||
|         b2BodyDef bd1, bd2; | ||||
|         bd1.type = b2_dynamicBody; | ||||
|         bd2.type = b2_dynamicBody; | ||||
|         bd1.position = m_offset; | ||||
|         bd2.position = p4 + m_offset; | ||||
|  | ||||
|         bd1.angularDamping = 10.0f; | ||||
|         bd2.angularDamping = 10.0f; | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|         b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|  | ||||
|         body1->CreateFixture(&fd1); | ||||
|         body2->CreateFixture(&fd2); | ||||
|  | ||||
|         b2DistanceJointDef djd; | ||||
|  | ||||
|         // Using a soft distance constraint can reduce some jitter. | ||||
|         // It also makes the structure seem a bit more fluid by | ||||
|         // acting like a suspension system. | ||||
|         djd.dampingRatio = 0.5f; | ||||
|         djd.frequencyHz = 10.0f; | ||||
|  | ||||
|         djd.Initialize(body1, body2, p2 + m_offset, p5 + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body1, body2, p3 + m_offset, p4 + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body1, m_wheel, p3 + m_offset, wheelAnchor + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body2, m_wheel, p6 + m_offset, wheelAnchor + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         b2RevoluteJointDef rjd; | ||||
|  | ||||
|         rjd.Initialize(body2, m_chassis, p4 + m_offset); | ||||
|         m_world->CreateJoint(&rjd); | ||||
|     } | ||||
|  | ||||
|     TheoJansen() | ||||
|     { | ||||
|         m_offset.Set(0.0f, 8.0f); | ||||
|         m_motorSpeed = 2.0f; | ||||
|         m_motorOn = true; | ||||
|         b2Vec2 pivot(0.0f, 0.8f); | ||||
|  | ||||
|         // Ground | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(-50.0f, 10.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(50.0f, 10.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Balls | ||||
|         for (int32 i = 0; i < 40; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.25f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-40.0f + 2.0f * i, 0.5f); | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|  | ||||
|         // Chassis | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.5f, 1.0f); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.density = 1.0f; | ||||
|             sd.shape = &shape; | ||||
|             sd.filter.groupIndex = -1; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position = pivot + m_offset; | ||||
|             m_chassis = m_world->CreateBody(&bd); | ||||
|             m_chassis->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.6f; | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.density = 1.0f; | ||||
|             sd.shape = &shape; | ||||
|             sd.filter.groupIndex = -1; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position = pivot + m_offset; | ||||
|             m_wheel = m_world->CreateBody(&bd); | ||||
|             m_wheel->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.Initialize(m_wheel, m_chassis, pivot + m_offset); | ||||
|             jd.collideConnected = false; | ||||
|             jd.motorSpeed = m_motorSpeed; | ||||
|             jd.maxMotorTorque = 400.0f; | ||||
|             jd.enableMotor = m_motorOn; | ||||
|             m_motorJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         b2Vec2 wheelAnchor; | ||||
|  | ||||
|         wheelAnchor = pivot + b2Vec2(0.0f, -0.8f); | ||||
|  | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|  | ||||
|         m_wheel->SetTransform(m_wheel->GetPosition(), 120.0f * b2_pi / 180.0f); | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|  | ||||
|         m_wheel->SetTransform(m_wheel->GetPosition(), -120.0f * b2_pi / 180.0f); | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, toggle motor = m"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_motorJoint->SetMotorSpeed(-m_motorSpeed); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_motorJoint->SetMotorSpeed(0.0f); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_motorJoint->SetMotorSpeed(m_motorSpeed); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_motorJoint->EnableMotor(!m_motorJoint->IsMotorEnabled()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new TheoJansen; | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_offset; | ||||
|     b2Body* m_chassis; | ||||
|     b2Body* m_wheel; | ||||
|     b2RevoluteJoint* m_motorJoint; | ||||
|     bool m_motorOn; | ||||
|     float32 m_motorSpeed; | ||||
| }; | ||||
|  | ||||
| #endif // THEO_JANSEN_H | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| // Inspired by a contribution by roman_m | ||||
| // Dimensions scooped from APE (http://www.cove.org/ape/index.htm) | ||||
|  | ||||
| #ifndef THEO_JANSEN_H | ||||
| #define THEO_JANSEN_H | ||||
|  | ||||
| class TheoJansen : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     void CreateLeg(float32 s, const b2Vec2& wheelAnchor) | ||||
|     { | ||||
|         b2Vec2 p1(5.4f * s, -6.1f); | ||||
|         b2Vec2 p2(7.2f * s, -1.2f); | ||||
|         b2Vec2 p3(4.3f * s, -1.9f); | ||||
|         b2Vec2 p4(3.1f * s, 0.8f); | ||||
|         b2Vec2 p5(6.0f * s, 1.5f); | ||||
|         b2Vec2 p6(2.5f * s, 3.7f); | ||||
|  | ||||
|         b2FixtureDef fd1, fd2; | ||||
|         fd1.filter.groupIndex = -1; | ||||
|         fd2.filter.groupIndex = -1; | ||||
|         fd1.density = 1.0f; | ||||
|         fd2.density = 1.0f; | ||||
|  | ||||
|         b2PolygonShape poly1, poly2; | ||||
|  | ||||
|         if (s > 0.0f) | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             vertices[0] = p1; | ||||
|             vertices[1] = p2; | ||||
|             vertices[2] = p3; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             vertices[0] = b2Vec2_zero; | ||||
|             vertices[1] = p5 - p4; | ||||
|             vertices[2] = p6 - p4; | ||||
|             poly2.Set(vertices, 3); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             b2Vec2 vertices[3]; | ||||
|  | ||||
|             vertices[0] = p1; | ||||
|             vertices[1] = p3; | ||||
|             vertices[2] = p2; | ||||
|             poly1.Set(vertices, 3); | ||||
|  | ||||
|             vertices[0] = b2Vec2_zero; | ||||
|             vertices[1] = p6 - p4; | ||||
|             vertices[2] = p5 - p4; | ||||
|             poly2.Set(vertices, 3); | ||||
|         } | ||||
|  | ||||
|         fd1.shape = &poly1; | ||||
|         fd2.shape = &poly2; | ||||
|  | ||||
|         b2BodyDef bd1, bd2; | ||||
|         bd1.type = b2_dynamicBody; | ||||
|         bd2.type = b2_dynamicBody; | ||||
|         bd1.position = m_offset; | ||||
|         bd2.position = p4 + m_offset; | ||||
|  | ||||
|         bd1.angularDamping = 10.0f; | ||||
|         bd2.angularDamping = 10.0f; | ||||
|  | ||||
|         b2Body* body1 = m_world->CreateBody(&bd1); | ||||
|         b2Body* body2 = m_world->CreateBody(&bd2); | ||||
|  | ||||
|         body1->CreateFixture(&fd1); | ||||
|         body2->CreateFixture(&fd2); | ||||
|  | ||||
|         b2DistanceJointDef djd; | ||||
|  | ||||
|         // Using a soft distance constraint can reduce some jitter. | ||||
|         // It also makes the structure seem a bit more fluid by | ||||
|         // acting like a suspension system. | ||||
|         djd.dampingRatio = 0.5f; | ||||
|         djd.frequencyHz = 10.0f; | ||||
|  | ||||
|         djd.Initialize(body1, body2, p2 + m_offset, p5 + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body1, body2, p3 + m_offset, p4 + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body1, m_wheel, p3 + m_offset, wheelAnchor + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         djd.Initialize(body2, m_wheel, p6 + m_offset, wheelAnchor + m_offset); | ||||
|         m_world->CreateJoint(&djd); | ||||
|  | ||||
|         b2RevoluteJointDef rjd; | ||||
|  | ||||
|         rjd.Initialize(body2, m_chassis, p4 + m_offset); | ||||
|         m_world->CreateJoint(&rjd); | ||||
|     } | ||||
|  | ||||
|     TheoJansen() | ||||
|     { | ||||
|         m_offset.Set(0.0f, 8.0f); | ||||
|         m_motorSpeed = 2.0f; | ||||
|         m_motorOn = true; | ||||
|         b2Vec2 pivot(0.0f, 0.8f); | ||||
|  | ||||
|         // Ground | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(-50.0f, 10.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(50.0f, 10.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         // Balls | ||||
|         for (int32 i = 0; i < 40; ++i) | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 0.25f; | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(-40.0f + 2.0f * i, 0.5f); | ||||
|  | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|         } | ||||
|  | ||||
|         // Chassis | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(2.5f, 1.0f); | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.density = 1.0f; | ||||
|             sd.shape = &shape; | ||||
|             sd.filter.groupIndex = -1; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position = pivot + m_offset; | ||||
|             m_chassis = m_world->CreateBody(&bd); | ||||
|             m_chassis->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.6f; | ||||
|  | ||||
|             b2FixtureDef sd; | ||||
|             sd.density = 1.0f; | ||||
|             sd.shape = &shape; | ||||
|             sd.filter.groupIndex = -1; | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position = pivot + m_offset; | ||||
|             m_wheel = m_world->CreateBody(&bd); | ||||
|             m_wheel->CreateFixture(&sd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.Initialize(m_wheel, m_chassis, pivot + m_offset); | ||||
|             jd.collideConnected = false; | ||||
|             jd.motorSpeed = m_motorSpeed; | ||||
|             jd.maxMotorTorque = 400.0f; | ||||
|             jd.enableMotor = m_motorOn; | ||||
|             m_motorJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         b2Vec2 wheelAnchor; | ||||
|  | ||||
|         wheelAnchor = pivot + b2Vec2(0.0f, -0.8f); | ||||
|  | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|  | ||||
|         m_wheel->SetTransform(m_wheel->GetPosition(), 120.0f * b2_pi / 180.0f); | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|  | ||||
|         m_wheel->SetTransform(m_wheel->GetPosition(), -120.0f * b2_pi / 180.0f); | ||||
|         CreateLeg(-1.0f, wheelAnchor); | ||||
|         CreateLeg(1.0f, wheelAnchor); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, toggle motor = m"); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'a': | ||||
|             m_motorJoint->SetMotorSpeed(-m_motorSpeed); | ||||
|             break; | ||||
|  | ||||
|         case 's': | ||||
|             m_motorJoint->SetMotorSpeed(0.0f); | ||||
|             break; | ||||
|  | ||||
|         case 'd': | ||||
|             m_motorJoint->SetMotorSpeed(m_motorSpeed); | ||||
|             break; | ||||
|  | ||||
|         case 'm': | ||||
|             m_motorJoint->EnableMotor(!m_motorJoint->IsMotorEnabled()); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new TheoJansen; | ||||
|     } | ||||
|  | ||||
|     b2Vec2 m_offset; | ||||
|     b2Body* m_chassis; | ||||
|     b2Body* m_wheel; | ||||
|     b2RevoluteJoint* m_motorJoint; | ||||
|     bool m_motorOn; | ||||
|     float32 m_motorSpeed; | ||||
| }; | ||||
|  | ||||
| #endif // THEO_JANSEN_H | ||||
|   | ||||
| @@ -1,156 +1,156 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TILES_H | ||||
| #define TILES_H | ||||
|  | ||||
| /// This stress tests the dynamic tree broad-phase. This also shows that tile | ||||
| /// based collision is _not_ smooth due to Box2D not knowing about adjacency. | ||||
| class Tiles : public Test | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_count = 20 | ||||
|     }; | ||||
|  | ||||
|     Tiles() | ||||
|     { | ||||
|         m_fixtureCount = 0; | ||||
|         b2Timer timer; | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2BodyDef bd; | ||||
|             bd.position.y = -a; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
| #if 1 | ||||
|             int32 N = 200; | ||||
|             int32 M = 10; | ||||
|             b2Vec2 position; | ||||
|             position.y = 0.0f; | ||||
|             for (int32 j = 0; j < M; ++j) | ||||
|             { | ||||
|                 position.x = -N * a; | ||||
|                 for (int32 i = 0; i < N; ++i) | ||||
|                 { | ||||
|                     b2PolygonShape shape; | ||||
|                     shape.SetAsBox(a, a, position, 0.0f); | ||||
|                     ground->CreateFixture(&shape, 0.0f); | ||||
|                     ++m_fixtureCount; | ||||
|                     position.x += 2.0f * a; | ||||
|                 } | ||||
|                 position.y -= 2.0f * a; | ||||
|             } | ||||
| #else | ||||
|             int32 N = 200; | ||||
|             int32 M = 10; | ||||
|             b2Vec2 position; | ||||
|             position.x = -N * a; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 position.y = 0.0f; | ||||
|                 for (int32 j = 0; j < M; ++j) | ||||
|                 { | ||||
|                     b2PolygonShape shape; | ||||
|                     shape.SetAsBox(a, a, position, 0.0f); | ||||
|                     ground->CreateFixture(&shape, 0.0f); | ||||
|                     position.y -= 2.0f * a; | ||||
|                 } | ||||
|                 position.x += 2.0f * a; | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, a); | ||||
|  | ||||
|             b2Vec2 x(-7.0f, 0.75f); | ||||
|             b2Vec2 y; | ||||
|             b2Vec2 deltaX(0.5625f, 1.25f); | ||||
|             b2Vec2 deltaY(1.125f, 0.0f); | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 y = x; | ||||
|  | ||||
|                 for (int32 j = i; j < e_count; ++j) | ||||
|                 { | ||||
|                     b2BodyDef bd; | ||||
|                     bd.type = b2_dynamicBody; | ||||
|                     bd.position = y; | ||||
|  | ||||
|                     //if (i == 0 && j == 0) | ||||
|                     //{ | ||||
|                     //  bd.allowSleep = false; | ||||
|                     //} | ||||
|                     //else | ||||
|                     //{ | ||||
|                     //  bd.allowSleep = true; | ||||
|                     //} | ||||
|  | ||||
|                     b2Body* body = m_world->CreateBody(&bd); | ||||
|                     body->CreateFixture(&shape, 5.0f); | ||||
|                     ++m_fixtureCount; | ||||
|                     y += deltaY; | ||||
|                 } | ||||
|  | ||||
|                 x += deltaX; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_createTime = timer.GetMilliseconds(); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         const b2ContactManager& cm = m_world->GetContactManager(); | ||||
|         int32 height = cm.m_broadPhase.GetTreeHeight(); | ||||
|         int32 leafCount = cm.m_broadPhase.GetProxyCount(); | ||||
|         int32 minimumNodeCount = 2 * leafCount - 1; | ||||
|         float32 minimumHeight = ceilf(logf(float32(minimumNodeCount)) / logf(2.0f)); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d, min = %d", height, int32(minimumHeight)); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "create time = %6.2f ms, fixture count = %d", | ||||
|             m_createTime, m_fixtureCount); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; | ||||
|  | ||||
|         //if (m_stepCount == 400) | ||||
|         //{ | ||||
|         //  tree->RebuildBottomUp(); | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Tiles; | ||||
|     } | ||||
|  | ||||
|     int32 m_fixtureCount; | ||||
|     float32 m_createTime; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TILES_H | ||||
| #define TILES_H | ||||
|  | ||||
| /// This stress tests the dynamic tree broad-phase. This also shows that tile | ||||
| /// based collision is _not_ smooth due to Box2D not knowing about adjacency. | ||||
| class Tiles : public Test | ||||
| { | ||||
| public: | ||||
|     enum | ||||
|     { | ||||
|         e_count = 20 | ||||
|     }; | ||||
|  | ||||
|     Tiles() | ||||
|     { | ||||
|         m_fixtureCount = 0; | ||||
|         b2Timer timer; | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2BodyDef bd; | ||||
|             bd.position.y = -a; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
| #if 1 | ||||
|             int32 N = 200; | ||||
|             int32 M = 10; | ||||
|             b2Vec2 position; | ||||
|             position.y = 0.0f; | ||||
|             for (int32 j = 0; j < M; ++j) | ||||
|             { | ||||
|                 position.x = -N * a; | ||||
|                 for (int32 i = 0; i < N; ++i) | ||||
|                 { | ||||
|                     b2PolygonShape shape; | ||||
|                     shape.SetAsBox(a, a, position, 0.0f); | ||||
|                     ground->CreateFixture(&shape, 0.0f); | ||||
|                     ++m_fixtureCount; | ||||
|                     position.x += 2.0f * a; | ||||
|                 } | ||||
|                 position.y -= 2.0f * a; | ||||
|             } | ||||
| #else | ||||
|             int32 N = 200; | ||||
|             int32 M = 10; | ||||
|             b2Vec2 position; | ||||
|             position.x = -N * a; | ||||
|             for (int32 i = 0; i < N; ++i) | ||||
|             { | ||||
|                 position.y = 0.0f; | ||||
|                 for (int32 j = 0; j < M; ++j) | ||||
|                 { | ||||
|                     b2PolygonShape shape; | ||||
|                     shape.SetAsBox(a, a, position, 0.0f); | ||||
|                     ground->CreateFixture(&shape, 0.0f); | ||||
|                     position.y -= 2.0f * a; | ||||
|                 } | ||||
|                 position.x += 2.0f * a; | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             float32 a = 0.5f; | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(a, a); | ||||
|  | ||||
|             b2Vec2 x(-7.0f, 0.75f); | ||||
|             b2Vec2 y; | ||||
|             b2Vec2 deltaX(0.5625f, 1.25f); | ||||
|             b2Vec2 deltaY(1.125f, 0.0f); | ||||
|  | ||||
|             for (int32 i = 0; i < e_count; ++i) | ||||
|             { | ||||
|                 y = x; | ||||
|  | ||||
|                 for (int32 j = i; j < e_count; ++j) | ||||
|                 { | ||||
|                     b2BodyDef bd; | ||||
|                     bd.type = b2_dynamicBody; | ||||
|                     bd.position = y; | ||||
|  | ||||
|                     //if (i == 0 && j == 0) | ||||
|                     //{ | ||||
|                     //  bd.allowSleep = false; | ||||
|                     //} | ||||
|                     //else | ||||
|                     //{ | ||||
|                     //  bd.allowSleep = true; | ||||
|                     //} | ||||
|  | ||||
|                     b2Body* body = m_world->CreateBody(&bd); | ||||
|                     body->CreateFixture(&shape, 5.0f); | ||||
|                     ++m_fixtureCount; | ||||
|                     y += deltaY; | ||||
|                 } | ||||
|  | ||||
|                 x += deltaX; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_createTime = timer.GetMilliseconds(); | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         const b2ContactManager& cm = m_world->GetContactManager(); | ||||
|         int32 height = cm.m_broadPhase.GetTreeHeight(); | ||||
|         int32 leafCount = cm.m_broadPhase.GetProxyCount(); | ||||
|         int32 minimumNodeCount = 2 * leafCount - 1; | ||||
|         float32 minimumHeight = ceilf(logf(float32(minimumNodeCount)) / logf(2.0f)); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d, min = %d", height, int32(minimumHeight)); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "create time = %6.2f ms, fixture count = %d", | ||||
|             m_createTime, m_fixtureCount); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; | ||||
|  | ||||
|         //if (m_stepCount == 400) | ||||
|         //{ | ||||
|         //  tree->RebuildBottomUp(); | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Tiles; | ||||
|     } | ||||
|  | ||||
|     int32 m_fixtureCount; | ||||
|     float32 m_createTime; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,131 +1,131 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TIME_OF_IMPACT_H | ||||
| #define TIME_OF_IMPACT_H | ||||
|  | ||||
| class TimeOfImpact : public Test | ||||
| { | ||||
| public: | ||||
|     TimeOfImpact() | ||||
|     { | ||||
|         m_shapeA.SetAsBox(25.0f, 5.0f); | ||||
|         m_shapeB.SetAsBox(2.5f, 2.5f); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new TimeOfImpact; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         b2Sweep sweepA; | ||||
|         sweepA.c0.Set(24.0f, -60.0f); | ||||
|         sweepA.a0 = 2.95f; | ||||
|         sweepA.c = sweepA.c0; | ||||
|         sweepA.a = sweepA.a0; | ||||
|         sweepA.localCenter.SetZero(); | ||||
|  | ||||
|         b2Sweep sweepB; | ||||
|         sweepB.c0.Set(53.474274f, -50.252514f); | ||||
|         sweepB.a0 = 513.36676f; // - 162.0f * b2_pi; | ||||
|         sweepB.c.Set(54.595478f, -51.083473f); | ||||
|         sweepB.a = 513.62781f; //  - 162.0f * b2_pi; | ||||
|         sweepB.localCenter.SetZero(); | ||||
|  | ||||
|         //sweepB.a0 -= 300.0f * b2_pi; | ||||
|         //sweepB.a -= 300.0f * b2_pi; | ||||
|  | ||||
|         b2TOIInput input; | ||||
|         input.proxyA.Set(&m_shapeA, 0); | ||||
|         input.proxyB.Set(&m_shapeB, 0); | ||||
|         input.sweepA = sweepA; | ||||
|         input.sweepB = sweepB; | ||||
|         input.tMax = 1.0f; | ||||
|  | ||||
|         b2TOIOutput output; | ||||
|  | ||||
|         b2TimeOfImpact(&output, &input); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "toi = %g", output.t); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         extern int32 b2_toiMaxIters, b2_toiMaxRootIters; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "max toi iters = %d, max root iters = %d", b2_toiMaxIters, b2_toiMaxRootIters); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         b2Vec2 vertices[b2_maxPolygonVertices]; | ||||
|  | ||||
|         b2Transform transformA; | ||||
|         sweepA.GetTransform(&transformA, 0.0f); | ||||
|         for (int32 i = 0; i < m_shapeA.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformA, m_shapeA.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeA.m_vertexCount, b2Color(0.9f, 0.9f, 0.9f)); | ||||
|  | ||||
|         b2Transform transformB; | ||||
|         sweepB.GetTransform(&transformB, 0.0f); | ||||
|  | ||||
|         b2Vec2 localPoint(2.0f, -0.1f); | ||||
|         b2Vec2 rB = b2Mul(transformB, localPoint) - sweepB.c0; | ||||
|         float32 wB = sweepB.a - sweepB.a0; | ||||
|         b2Vec2 vB = sweepB.c - sweepB.c0; | ||||
|         b2Vec2 v = vB + b2Cross(wB, rB); | ||||
|  | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.5f, 0.9f, 0.5f)); | ||||
|  | ||||
|         sweepB.GetTransform(&transformB, output.t); | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.5f, 0.7f, 0.9f)); | ||||
|  | ||||
|         sweepB.GetTransform(&transformB, 1.0f); | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.9f, 0.5f, 0.5f)); | ||||
|  | ||||
| #if 0 | ||||
|         for (float32 t = 0.0f; t < 1.0f; t += 0.1f) | ||||
|         { | ||||
|             sweepB.GetTransform(&transformB, t); | ||||
|             for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.9f, 0.5f, 0.5f)); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     b2PolygonShape m_shapeA; | ||||
|     b2PolygonShape m_shapeB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TIME_OF_IMPACT_H | ||||
| #define TIME_OF_IMPACT_H | ||||
|  | ||||
| class TimeOfImpact : public Test | ||||
| { | ||||
| public: | ||||
|     TimeOfImpact() | ||||
|     { | ||||
|         m_shapeA.SetAsBox(25.0f, 5.0f); | ||||
|         m_shapeB.SetAsBox(2.5f, 2.5f); | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new TimeOfImpact; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         b2Sweep sweepA; | ||||
|         sweepA.c0.Set(24.0f, -60.0f); | ||||
|         sweepA.a0 = 2.95f; | ||||
|         sweepA.c = sweepA.c0; | ||||
|         sweepA.a = sweepA.a0; | ||||
|         sweepA.localCenter.SetZero(); | ||||
|  | ||||
|         b2Sweep sweepB; | ||||
|         sweepB.c0.Set(53.474274f, -50.252514f); | ||||
|         sweepB.a0 = 513.36676f; // - 162.0f * b2_pi; | ||||
|         sweepB.c.Set(54.595478f, -51.083473f); | ||||
|         sweepB.a = 513.62781f; //  - 162.0f * b2_pi; | ||||
|         sweepB.localCenter.SetZero(); | ||||
|  | ||||
|         //sweepB.a0 -= 300.0f * b2_pi; | ||||
|         //sweepB.a -= 300.0f * b2_pi; | ||||
|  | ||||
|         b2TOIInput input; | ||||
|         input.proxyA.Set(&m_shapeA, 0); | ||||
|         input.proxyB.Set(&m_shapeB, 0); | ||||
|         input.sweepA = sweepA; | ||||
|         input.sweepB = sweepB; | ||||
|         input.tMax = 1.0f; | ||||
|  | ||||
|         b2TOIOutput output; | ||||
|  | ||||
|         b2TimeOfImpact(&output, &input); | ||||
|  | ||||
|         m_debugDraw.DrawString(5, m_textLine, "toi = %g", output.t); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         extern int32 b2_toiMaxIters, b2_toiMaxRootIters; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "max toi iters = %d, max root iters = %d", b2_toiMaxIters, b2_toiMaxRootIters); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         b2Vec2 vertices[b2_maxPolygonVertices]; | ||||
|  | ||||
|         b2Transform transformA; | ||||
|         sweepA.GetTransform(&transformA, 0.0f); | ||||
|         for (int32 i = 0; i < m_shapeA.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformA, m_shapeA.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeA.m_vertexCount, b2Color(0.9f, 0.9f, 0.9f)); | ||||
|  | ||||
|         b2Transform transformB; | ||||
|         sweepB.GetTransform(&transformB, 0.0f); | ||||
|  | ||||
|         b2Vec2 localPoint(2.0f, -0.1f); | ||||
|         b2Vec2 rB = b2Mul(transformB, localPoint) - sweepB.c0; | ||||
|         float32 wB = sweepB.a - sweepB.a0; | ||||
|         b2Vec2 vB = sweepB.c - sweepB.c0; | ||||
|         b2Vec2 v = vB + b2Cross(wB, rB); | ||||
|  | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.5f, 0.9f, 0.5f)); | ||||
|  | ||||
|         sweepB.GetTransform(&transformB, output.t); | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.5f, 0.7f, 0.9f)); | ||||
|  | ||||
|         sweepB.GetTransform(&transformB, 1.0f); | ||||
|         for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|         { | ||||
|             vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|         } | ||||
|         m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.9f, 0.5f, 0.5f)); | ||||
|  | ||||
| #if 0 | ||||
|         for (float32 t = 0.0f; t < 1.0f; t += 0.1f) | ||||
|         { | ||||
|             sweepB.GetTransform(&transformB, t); | ||||
|             for (int32 i = 0; i < m_shapeB.m_vertexCount; ++i) | ||||
|             { | ||||
|                 vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); | ||||
|             } | ||||
|             m_debugDraw.DrawPolygon(vertices, m_shapeB.m_vertexCount, b2Color(0.9f, 0.5f, 0.5f)); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     b2PolygonShape m_shapeA; | ||||
|     b2PolygonShape m_shapeB; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,99 +1,99 @@ | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TUMBLER_H | ||||
| #define TUMBLER_H | ||||
|  | ||||
| class Tumbler : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 800 | ||||
|     }; | ||||
|  | ||||
|     Tumbler() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.allowSleep = false; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 10.0f, b2Vec2( 10.0f, 0.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(0.5f, 10.0f, b2Vec2(-10.0f, 0.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, 10.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, -10.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = body; | ||||
|             jd.localAnchorA.Set(0.0f, 10.0f); | ||||
|             jd.localAnchorB.Set(0.0f, 0.0f); | ||||
|             jd.referenceAngle = 0.0f; | ||||
|             jd.motorSpeed = 0.05f * b2_pi; | ||||
|             jd.maxMotorTorque = 1e8f; | ||||
|             jd.enableMotor = true; | ||||
|             m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         if (m_count < e_count) | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.125f, 0.125f); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             ++m_count; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Tumbler; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2011 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef TUMBLER_H | ||||
| #define TUMBLER_H | ||||
|  | ||||
| class Tumbler : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_count = 800 | ||||
|     }; | ||||
|  | ||||
|     Tumbler() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.allowSleep = false; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 10.0f, b2Vec2( 10.0f, 0.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(0.5f, 10.0f, b2Vec2(-10.0f, 0.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, 10.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|             shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, -10.0f), 0.0); | ||||
|             body->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2RevoluteJointDef jd; | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = body; | ||||
|             jd.localAnchorA.Set(0.0f, 10.0f); | ||||
|             jd.localAnchorB.Set(0.0f, 0.0f); | ||||
|             jd.referenceAngle = 0.0f; | ||||
|             jd.motorSpeed = 0.05f * b2_pi; | ||||
|             jd.maxMotorTorque = 1e8f; | ||||
|             jd.enableMotor = true; | ||||
|             m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | ||||
|         } | ||||
|  | ||||
|         m_count = 0; | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|  | ||||
|         if (m_count < e_count) | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|             bd.position.Set(0.0f, 10.0f); | ||||
|             b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.125f, 0.125f); | ||||
|             body->CreateFixture(&shape, 1.0f); | ||||
|  | ||||
|             ++m_count; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Tumbler; | ||||
|     } | ||||
|  | ||||
|     b2RevoluteJoint* m_joint; | ||||
|     int32 m_count; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,124 +1,124 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VARYING_FRICTION_H | ||||
| #define VARYING_FRICTION_H | ||||
|  | ||||
| class VaryingFriction : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     VaryingFriction() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-4.0f, 22.0f); | ||||
|             bd.angle = -0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(10.5f, 19.0f); | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(4.0f, 14.0f); | ||||
|             bd.angle = 0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-10.5f, 11.0f); | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-4.0f, 6.0f); | ||||
|             bd.angle = -0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 25.0f; | ||||
|  | ||||
|             float friction[5] = {0.75f, 0.5f, 0.35f, 0.1f, 0.0f}; | ||||
|  | ||||
|             for (int i = 0; i < 5; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-15.0f + 4.0f * i, 28.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 fd.friction = friction[i]; | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VaryingFriction; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VARYING_FRICTION_H | ||||
| #define VARYING_FRICTION_H | ||||
|  | ||||
| class VaryingFriction : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     VaryingFriction() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-4.0f, 22.0f); | ||||
|             bd.angle = -0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(10.5f, 19.0f); | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(4.0f, 14.0f); | ||||
|             bd.angle = 0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.25f, 1.0f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-10.5f, 11.0f); | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(13.0f, 0.25f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.position.Set(-4.0f, 6.0f); | ||||
|             bd.angle = -0.25f; | ||||
|  | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 25.0f; | ||||
|  | ||||
|             float friction[5] = {0.75f, 0.5f, 0.35f, 0.1f, 0.0f}; | ||||
|  | ||||
|             for (int i = 0; i < 5; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-15.0f + 4.0f * i, 28.0f); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 fd.friction = friction[i]; | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VaryingFriction; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,69 +1,69 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VARYING_RESTITUTION_H | ||||
| #define VARYING_RESTITUTION_H | ||||
|  | ||||
| // Note: even with a restitution of 1.0, there is some energy change | ||||
| // due to position correction. | ||||
| class VaryingRestitution : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     VaryingRestitution() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             float32 restitution[7] = {0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f}; | ||||
|  | ||||
|             for (int32 i = 0; i < 7; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + 3.0f * i, 20.0f); | ||||
|  | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 fd.restitution = restitution[i]; | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VaryingRestitution; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VARYING_RESTITUTION_H | ||||
| #define VARYING_RESTITUTION_H | ||||
|  | ||||
| // Note: even with a restitution of 1.0, there is some energy change | ||||
| // due to position correction. | ||||
| class VaryingRestitution : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     VaryingRestitution() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2CircleShape shape; | ||||
|             shape.m_radius = 1.0f; | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|  | ||||
|             float32 restitution[7] = {0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f}; | ||||
|  | ||||
|             for (int32 i = 0; i < 7; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.position.Set(-10.0f + 3.0f * i, 20.0f); | ||||
|  | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 fd.restitution = restitution[i]; | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VaryingRestitution; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,165 +1,165 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VERTICAL_STACK_H | ||||
| #define VERTICAL_STACK_H | ||||
|  | ||||
| class VerticalStack : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_columnCount = 5, | ||||
|         e_rowCount = 16 | ||||
|         //e_columnCount = 1, | ||||
|         //e_rowCount = 1 | ||||
|     }; | ||||
|  | ||||
|     VerticalStack() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(20.0f, 0.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         float32 xs[5] = {0.0f, -10.0f, -5.0f, 5.0f, 10.0f}; | ||||
|  | ||||
|         for (int32 j = 0; j < e_columnCount; ++j) | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             for (int i = 0; i < e_rowCount; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|  | ||||
|                 int32 n = j * e_rowCount + i; | ||||
|                 b2Assert(n < e_rowCount * e_columnCount); | ||||
|                 m_indices[n] = n; | ||||
|                 bd.userData = m_indices + n; | ||||
|  | ||||
|                 float32 x = 0.0f; | ||||
|                 //float32 x = RandomFloat(-0.02f, 0.02f); | ||||
|                 //float32 x = i % 2 == 0 ? -0.025f : 0.025f; | ||||
|                 bd.position.Set(xs[j] + x, 0.752f + 1.54f * i); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[n] = body; | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_bullet = NULL; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case ',': | ||||
|             if (m_bullet != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bullet); | ||||
|                 m_bullet = NULL; | ||||
|             } | ||||
|  | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 0.25f; | ||||
|  | ||||
|                 b2FixtureDef fd; | ||||
|                 fd.shape = &shape; | ||||
|                 fd.density = 20.0f; | ||||
|                 fd.restitution = 0.05f; | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.bullet = true; | ||||
|                 bd.position.Set(-31.0f, 5.0f); | ||||
|  | ||||
|                 m_bullet = m_world->CreateBody(&bd); | ||||
|                 m_bullet->CreateFixture(&fd); | ||||
|  | ||||
|                 m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (,) to launch a bullet."); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //if (m_stepCount == 300) | ||||
|         //{ | ||||
|         //  if (m_bullet != NULL) | ||||
|         //  { | ||||
|         //      m_world->DestroyBody(m_bullet); | ||||
|         //      m_bullet = NULL; | ||||
|         //  } | ||||
|  | ||||
|         //  { | ||||
|         //      b2CircleShape shape; | ||||
|         //      shape.m_radius = 0.25f; | ||||
|  | ||||
|         //      b2FixtureDef fd; | ||||
|         //      fd.shape = &shape; | ||||
|         //      fd.density = 20.0f; | ||||
|         //      fd.restitution = 0.05f; | ||||
|  | ||||
|         //      b2BodyDef bd; | ||||
|         //      bd.type = b2_dynamicBody; | ||||
|         //      bd.bullet = true; | ||||
|         //      bd.position.Set(-31.0f, 5.0f); | ||||
|  | ||||
|         //      m_bullet = m_world->CreateBody(&bd); | ||||
|         //      m_bullet->CreateFixture(&fd); | ||||
|  | ||||
|         //      m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); | ||||
|         //  } | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VerticalStack; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bullet; | ||||
|     b2Body* m_bodies[e_rowCount * e_columnCount]; | ||||
|     int32 m_indices[e_rowCount * e_columnCount]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef VERTICAL_STACK_H | ||||
| #define VERTICAL_STACK_H | ||||
|  | ||||
| class VerticalStack : public Test | ||||
| { | ||||
| public: | ||||
|  | ||||
|     enum | ||||
|     { | ||||
|         e_columnCount = 5, | ||||
|         e_rowCount = 16 | ||||
|         //e_columnCount = 1, | ||||
|         //e_rowCount = 1 | ||||
|     }; | ||||
|  | ||||
|     VerticalStack() | ||||
|     { | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             b2Body* ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|  | ||||
|             shape.Set(b2Vec2(20.0f, 0.0f), b2Vec2(20.0f, 20.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         float32 xs[5] = {0.0f, -10.0f, -5.0f, 5.0f, 10.0f}; | ||||
|  | ||||
|         for (int32 j = 0; j < e_columnCount; ++j) | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2FixtureDef fd; | ||||
|             fd.shape = &shape; | ||||
|             fd.density = 1.0f; | ||||
|             fd.friction = 0.3f; | ||||
|  | ||||
|             for (int i = 0; i < e_rowCount; ++i) | ||||
|             { | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|  | ||||
|                 int32 n = j * e_rowCount + i; | ||||
|                 b2Assert(n < e_rowCount * e_columnCount); | ||||
|                 m_indices[n] = n; | ||||
|                 bd.userData = m_indices + n; | ||||
|  | ||||
|                 float32 x = 0.0f; | ||||
|                 //float32 x = RandomFloat(-0.02f, 0.02f); | ||||
|                 //float32 x = i % 2 == 0 ? -0.025f : 0.025f; | ||||
|                 bd.position.Set(xs[j] + x, 0.752f + 1.54f * i); | ||||
|                 b2Body* body = m_world->CreateBody(&bd); | ||||
|  | ||||
|                 m_bodies[n] = body; | ||||
|  | ||||
|                 body->CreateFixture(&fd); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         m_bullet = NULL; | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case ',': | ||||
|             if (m_bullet != NULL) | ||||
|             { | ||||
|                 m_world->DestroyBody(m_bullet); | ||||
|                 m_bullet = NULL; | ||||
|             } | ||||
|  | ||||
|             { | ||||
|                 b2CircleShape shape; | ||||
|                 shape.m_radius = 0.25f; | ||||
|  | ||||
|                 b2FixtureDef fd; | ||||
|                 fd.shape = &shape; | ||||
|                 fd.density = 20.0f; | ||||
|                 fd.restitution = 0.05f; | ||||
|  | ||||
|                 b2BodyDef bd; | ||||
|                 bd.type = b2_dynamicBody; | ||||
|                 bd.bullet = true; | ||||
|                 bd.position.Set(-31.0f, 5.0f); | ||||
|  | ||||
|                 m_bullet = m_world->CreateBody(&bd); | ||||
|                 m_bullet->CreateFixture(&fd); | ||||
|  | ||||
|                 m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (,) to launch a bullet."); | ||||
|         m_textLine += 15; | ||||
|  | ||||
|         //if (m_stepCount == 300) | ||||
|         //{ | ||||
|         //  if (m_bullet != NULL) | ||||
|         //  { | ||||
|         //      m_world->DestroyBody(m_bullet); | ||||
|         //      m_bullet = NULL; | ||||
|         //  } | ||||
|  | ||||
|         //  { | ||||
|         //      b2CircleShape shape; | ||||
|         //      shape.m_radius = 0.25f; | ||||
|  | ||||
|         //      b2FixtureDef fd; | ||||
|         //      fd.shape = &shape; | ||||
|         //      fd.density = 20.0f; | ||||
|         //      fd.restitution = 0.05f; | ||||
|  | ||||
|         //      b2BodyDef bd; | ||||
|         //      bd.type = b2_dynamicBody; | ||||
|         //      bd.bullet = true; | ||||
|         //      bd.position.Set(-31.0f, 5.0f); | ||||
|  | ||||
|         //      m_bullet = m_world->CreateBody(&bd); | ||||
|         //      m_bullet->CreateFixture(&fd); | ||||
|  | ||||
|         //      m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); | ||||
|         //  } | ||||
|         //} | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new VerticalStack; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bullet; | ||||
|     b2Body* m_bodies[e_rowCount * e_columnCount]; | ||||
|     int32 m_indices[e_rowCount * e_columnCount]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,209 +1,209 @@ | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef WEB_H | ||||
| #define WEB_H | ||||
|  | ||||
| // This tests distance joints, body destruction, and joint destruction. | ||||
| class Web : public Test | ||||
| { | ||||
| public: | ||||
|     Web() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position.Set(-5.0f, 5.0f); | ||||
|             m_bodies[0] = m_world->CreateBody(&bd); | ||||
|             m_bodies[0]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(5.0f, 5.0f); | ||||
|             m_bodies[1] = m_world->CreateBody(&bd); | ||||
|             m_bodies[1]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(5.0f, 15.0f); | ||||
|             m_bodies[2] = m_world->CreateBody(&bd); | ||||
|             m_bodies[2]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(-5.0f, 15.0f); | ||||
|             m_bodies[3] = m_world->CreateBody(&bd); | ||||
|             m_bodies[3]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2DistanceJointDef jd; | ||||
|             b2Vec2 p1, p2, d; | ||||
|  | ||||
|             jd.frequencyHz = 2.0f; | ||||
|             jd.dampingRatio = 0.0f; | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[0]; | ||||
|             jd.localAnchorA.Set(-10.0f, 0.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[0] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[1]; | ||||
|             jd.localAnchorA.Set(10.0f, 0.0f); | ||||
|             jd.localAnchorB.Set(0.5f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[1] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[2]; | ||||
|             jd.localAnchorA.Set(10.0f, 20.0f); | ||||
|             jd.localAnchorB.Set(0.5f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[2] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[3]; | ||||
|             jd.localAnchorA.Set(-10.0f, 20.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[3] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[0]; | ||||
|             jd.bodyB = m_bodies[1]; | ||||
|             jd.localAnchorA.Set(0.5f, 0.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, 0.0f);; | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[4] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[1]; | ||||
|             jd.bodyB = m_bodies[2]; | ||||
|             jd.localAnchorA.Set(0.0f, 0.5f); | ||||
|             jd.localAnchorB.Set(0.0f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[5] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[2]; | ||||
|             jd.bodyB = m_bodies[3]; | ||||
|             jd.localAnchorA.Set(-0.5f, 0.0f); | ||||
|             jd.localAnchorB.Set(0.5f, 0.0f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[6] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[3]; | ||||
|             jd.bodyB = m_bodies[0]; | ||||
|             jd.localAnchorA.Set(0.0f, -0.5f); | ||||
|             jd.localAnchorB.Set(0.0f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[7] = m_world->CreateJoint(&jd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'b': | ||||
|             for (int32 i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 if (m_bodies[i]) | ||||
|                 { | ||||
|                     m_world->DestroyBody(m_bodies[i]); | ||||
|                     m_bodies[i] = NULL; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'j': | ||||
|             for (int32 i = 0; i < 8; ++i) | ||||
|             { | ||||
|                 if (m_joints[i]) | ||||
|                 { | ||||
|                     m_world->DestroyJoint(m_joints[i]); | ||||
|                     m_joints[i] = NULL; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "This demonstrates a soft distance joint."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (b) to delete a body, (j) to delete a joint"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     void JointDestroyed(b2Joint* joint) | ||||
|     { | ||||
|         for (int32 i = 0; i < 8; ++i) | ||||
|         { | ||||
|             if (m_joints[i] == joint) | ||||
|             { | ||||
|                 m_joints[i] = NULL; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Web; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bodies[4]; | ||||
|     b2Joint* m_joints[8]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| /* | ||||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | ||||
| * | ||||
| * This software is provided 'as-is', without any express or implied | ||||
| * warranty.  In no event will the authors be held liable for any damages | ||||
| * arising from the use of this software. | ||||
| * Permission is granted to anyone to use this software for any purpose, | ||||
| * including commercial applications, and to alter it and redistribute it | ||||
| * freely, subject to the following restrictions: | ||||
| * 1. The origin of this software must not be misrepresented; you must not | ||||
| * claim that you wrote the original software. If you use this software | ||||
| * in a product, an acknowledgment in the product documentation would be | ||||
| * appreciated but is not required. | ||||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||||
| * misrepresented as being the original software. | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
|  | ||||
| #ifndef WEB_H | ||||
| #define WEB_H | ||||
|  | ||||
| // This tests distance joints, body destruction, and joint destruction. | ||||
| class Web : public Test | ||||
| { | ||||
| public: | ||||
|     Web() | ||||
|     { | ||||
|         b2Body* ground = NULL; | ||||
|         { | ||||
|             b2BodyDef bd; | ||||
|             ground = m_world->CreateBody(&bd); | ||||
|  | ||||
|             b2EdgeShape shape; | ||||
|             shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | ||||
|             ground->CreateFixture(&shape, 0.0f); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|             b2PolygonShape shape; | ||||
|             shape.SetAsBox(0.5f, 0.5f); | ||||
|  | ||||
|             b2BodyDef bd; | ||||
|             bd.type = b2_dynamicBody; | ||||
|  | ||||
|             bd.position.Set(-5.0f, 5.0f); | ||||
|             m_bodies[0] = m_world->CreateBody(&bd); | ||||
|             m_bodies[0]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(5.0f, 5.0f); | ||||
|             m_bodies[1] = m_world->CreateBody(&bd); | ||||
|             m_bodies[1]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(5.0f, 15.0f); | ||||
|             m_bodies[2] = m_world->CreateBody(&bd); | ||||
|             m_bodies[2]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             bd.position.Set(-5.0f, 15.0f); | ||||
|             m_bodies[3] = m_world->CreateBody(&bd); | ||||
|             m_bodies[3]->CreateFixture(&shape, 5.0f); | ||||
|  | ||||
|             b2DistanceJointDef jd; | ||||
|             b2Vec2 p1, p2, d; | ||||
|  | ||||
|             jd.frequencyHz = 2.0f; | ||||
|             jd.dampingRatio = 0.0f; | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[0]; | ||||
|             jd.localAnchorA.Set(-10.0f, 0.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[0] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[1]; | ||||
|             jd.localAnchorA.Set(10.0f, 0.0f); | ||||
|             jd.localAnchorB.Set(0.5f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[1] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[2]; | ||||
|             jd.localAnchorA.Set(10.0f, 20.0f); | ||||
|             jd.localAnchorB.Set(0.5f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[2] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = ground; | ||||
|             jd.bodyB = m_bodies[3]; | ||||
|             jd.localAnchorA.Set(-10.0f, 20.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[3] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[0]; | ||||
|             jd.bodyB = m_bodies[1]; | ||||
|             jd.localAnchorA.Set(0.5f, 0.0f); | ||||
|             jd.localAnchorB.Set(-0.5f, 0.0f);; | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[4] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[1]; | ||||
|             jd.bodyB = m_bodies[2]; | ||||
|             jd.localAnchorA.Set(0.0f, 0.5f); | ||||
|             jd.localAnchorB.Set(0.0f, -0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[5] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[2]; | ||||
|             jd.bodyB = m_bodies[3]; | ||||
|             jd.localAnchorA.Set(-0.5f, 0.0f); | ||||
|             jd.localAnchorB.Set(0.5f, 0.0f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[6] = m_world->CreateJoint(&jd); | ||||
|  | ||||
|             jd.bodyA = m_bodies[3]; | ||||
|             jd.bodyB = m_bodies[0]; | ||||
|             jd.localAnchorA.Set(0.0f, -0.5f); | ||||
|             jd.localAnchorB.Set(0.0f, 0.5f); | ||||
|             p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); | ||||
|             p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); | ||||
|             d = p2 - p1; | ||||
|             jd.length = d.Length(); | ||||
|             m_joints[7] = m_world->CreateJoint(&jd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Keyboard(unsigned char key) | ||||
|     { | ||||
|         switch (key) | ||||
|         { | ||||
|         case 'b': | ||||
|             for (int32 i = 0; i < 4; ++i) | ||||
|             { | ||||
|                 if (m_bodies[i]) | ||||
|                 { | ||||
|                     m_world->DestroyBody(m_bodies[i]); | ||||
|                     m_bodies[i] = NULL; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case 'j': | ||||
|             for (int32 i = 0; i < 8; ++i) | ||||
|             { | ||||
|                 if (m_joints[i]) | ||||
|                 { | ||||
|                     m_world->DestroyJoint(m_joints[i]); | ||||
|                     m_joints[i] = NULL; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Step(Settings* settings) | ||||
|     { | ||||
|         Test::Step(settings); | ||||
|         m_debugDraw.DrawString(5, m_textLine, "This demonstrates a soft distance joint."); | ||||
|         m_textLine += 15; | ||||
|         m_debugDraw.DrawString(5, m_textLine, "Press: (b) to delete a body, (j) to delete a joint"); | ||||
|         m_textLine += 15; | ||||
|     } | ||||
|  | ||||
|     void JointDestroyed(b2Joint* joint) | ||||
|     { | ||||
|         for (int32 i = 0; i < 8; ++i) | ||||
|         { | ||||
|             if (m_joints[i] == joint) | ||||
|             { | ||||
|                 m_joints[i] = NULL; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Test* Create() | ||||
|     { | ||||
|         return new Web; | ||||
|     } | ||||
|  | ||||
|     b2Body* m_bodies[4]; | ||||
|     b2Joint* m_joints[8]; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,246 +1,245 @@ | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2020 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <JuceHeader.h> | ||||
|  | ||||
| #ifndef PIP_DEMO_UTILITIES_INCLUDED | ||||
|  #define PIP_DEMO_UTILITIES_INCLUDED 1 | ||||
| #endif | ||||
|  | ||||
| //============================================================================== | ||||
| /* | ||||
|     This file contains a bunch of miscellaneous utilities that are | ||||
|     used by the various demos. | ||||
| */ | ||||
|  | ||||
| //============================================================================== | ||||
| inline Colour getRandomColour (float brightness) noexcept | ||||
| { | ||||
|     return Colour::fromHSV (Random::getSystemRandom().nextFloat(), 0.5f, brightness, 1.0f); | ||||
| } | ||||
|  | ||||
| inline Colour getRandomBrightColour() noexcept  { return getRandomColour (0.8f); } | ||||
| inline Colour getRandomDarkColour() noexcept    { return getRandomColour (0.3f); } | ||||
|  | ||||
| inline Colour getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour uiColour, Colour fallback = Colour (0xff4d4d4d)) noexcept | ||||
| { | ||||
|     if (auto* v4 = dynamic_cast<LookAndFeel_V4*> (&LookAndFeel::getDefaultLookAndFeel())) | ||||
|         return v4->getCurrentColourScheme().getUIColour (uiColour); | ||||
|  | ||||
|     return fallback; | ||||
| } | ||||
|  | ||||
| inline File getExamplesDirectory() noexcept | ||||
| { | ||||
|    #ifdef PIP_JUCE_EXAMPLES_DIRECTORY | ||||
|     MemoryOutputStream mo; | ||||
|  | ||||
|     auto success = Base64::convertFromBase64 (mo, JUCE_STRINGIFY (PIP_JUCE_EXAMPLES_DIRECTORY)); | ||||
|     ignoreUnused (success); | ||||
|     jassert (success); | ||||
|  | ||||
|     return mo.toString(); | ||||
|    #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING | ||||
|     return File { CharPointer_UTF8 { PIP_JUCE_EXAMPLES_DIRECTORY_STRING } }; | ||||
|    #else | ||||
|     auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile); | ||||
|     auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples"); | ||||
|  | ||||
|     if (exampleDir.exists()) | ||||
|         return exampleDir; | ||||
|  | ||||
|     // keep track of the number of parent directories so we don't go on endlessly | ||||
|     for (int numTries = 0; numTries < 15; ++numTries) | ||||
|     { | ||||
|         if (currentFile.getFileName() == "examples") | ||||
|             return currentFile; | ||||
|  | ||||
|         const auto sibling = currentFile.getSiblingFile ("examples"); | ||||
|  | ||||
|         if (sibling.exists()) | ||||
|             return sibling; | ||||
|  | ||||
|         currentFile = currentFile.getParentDirectory(); | ||||
|     } | ||||
|  | ||||
|     return currentFile; | ||||
|    #endif | ||||
| } | ||||
|  | ||||
| inline std::unique_ptr<InputStream> createAssetInputStream (const char* resourcePath) | ||||
| { | ||||
|   #if JUCE_ANDROID | ||||
|     ZipFile apkZip (File::getSpecialLocation (File::invokedExecutableFile)); | ||||
|     return std::unique_ptr<InputStream> (apkZip.createStreamForEntry (apkZip.getIndexOfFileName ("assets/" + String (resourcePath)))); | ||||
|   #else | ||||
|    #if JUCE_IOS | ||||
|     auto assetsDir = File::getSpecialLocation (File::currentExecutableFile) | ||||
|                           .getParentDirectory().getChildFile ("Assets"); | ||||
|    #elif JUCE_MAC | ||||
|     auto assetsDir = File::getSpecialLocation (File::currentExecutableFile) | ||||
|                           .getParentDirectory().getParentDirectory().getChildFile ("Resources").getChildFile ("Assets"); | ||||
|  | ||||
|     if (! assetsDir.exists()) | ||||
|         assetsDir = getExamplesDirectory().getChildFile ("Assets"); | ||||
|    #else | ||||
|     auto assetsDir = getExamplesDirectory().getChildFile ("Assets"); | ||||
|    #endif | ||||
|  | ||||
|     auto resourceFile = assetsDir.getChildFile (resourcePath); | ||||
|     jassert (resourceFile.existsAsFile()); | ||||
|  | ||||
|     return resourceFile.createInputStream(); | ||||
|   #endif | ||||
| } | ||||
|  | ||||
| inline Image getImageFromAssets (const char* assetName) | ||||
| { | ||||
|     auto hashCode = (String (assetName) + "@juce_demo_assets").hashCode64(); | ||||
|     auto img = ImageCache::getFromHashCode (hashCode); | ||||
|  | ||||
|     if (img.isNull()) | ||||
|     { | ||||
|         std::unique_ptr<InputStream> juceIconStream (createAssetInputStream (assetName)); | ||||
|  | ||||
|         if (juceIconStream == nullptr) | ||||
|             return {}; | ||||
|  | ||||
|         img = ImageFileFormat::loadFrom (*juceIconStream); | ||||
|  | ||||
|         ImageCache::addImageToCache (img, hashCode); | ||||
|     } | ||||
|  | ||||
|     return img; | ||||
| } | ||||
|  | ||||
| inline String loadEntireAssetIntoString (const char* assetName) | ||||
| { | ||||
|     std::unique_ptr<InputStream> input (createAssetInputStream (assetName)); | ||||
|  | ||||
|     if (input == nullptr) | ||||
|         return {}; | ||||
|  | ||||
|     return input->readString(); | ||||
| } | ||||
|  | ||||
| //============================================================================== | ||||
| inline Path getJUCELogoPath() | ||||
| { | ||||
|     return Drawable::parseSVGPath ( | ||||
|         "M72.87 84.28A42.36 42.36 0 0130.4 42.14a42.48 42.48 0 0184.95 0 42.36 42.36 0 01-42.48 42.14zm0-78.67A36.74 36.74 0 0036 42.14a36.88 36.88 0 0073.75 0A36.75 36.75 0 0072.87 5.61z" | ||||
|         "M77.62 49.59a177.77 177.77 0 008.74 18.93A4.38 4.38 0 0092.69 70a34.5 34.5 0 008.84-9 4.3 4.3 0 00-2.38-6.49A176.73 176.73 0 0180 47.32a1.78 1.78 0 00-2.38 2.27zM81.05 44.27a169.68 169.68 0 0020.13 7.41 4.39 4.39 0 005.52-3.41 34.42 34.42 0 00.55-6.13 33.81 33.81 0 00-.67-6.72 4.37 4.37 0 00-6.31-3A192.32 192.32 0 0181.1 41a1.76 1.76 0 00-.05 3.27zM74.47 50.44a1.78 1.78 0 00-3.29 0 165.54 165.54 0 00-7.46 19.89 4.33 4.33 0 003.47 5.48 35.49 35.49 0 005.68.46 34.44 34.44 0 007.13-.79 4.32 4.32 0 003-6.25 187.83 187.83 0 01-8.53-18.79zM71.59 34.12a1.78 1.78 0 003.29.05 163.9 163.9 0 007.52-20.11A4.34 4.34 0 0079 8.59a35.15 35.15 0 00-13.06.17 4.32 4.32 0 00-3 6.26 188.41 188.41 0 018.65 19.1zM46.32 30.3a176.2 176.2 0 0120 7.48 1.78 1.78 0 002.37-2.28 180.72 180.72 0 00-9.13-19.84 4.38 4.38 0 00-6.33-1.47 34.27 34.27 0 00-9.32 9.65 4.31 4.31 0 002.41 6.46zM68.17 49.18a1.77 1.77 0 00-2.29-2.34 181.71 181.71 0 00-19.51 8.82A4.3 4.3 0 0044.91 62a34.36 34.36 0 009.42 8.88 4.36 4.36 0 006.5-2.38 175.11 175.11 0 017.34-19.32zM77.79 35.59a1.78 1.78 0 002.3 2.35 182.51 182.51 0 0019.6-8.88 4.3 4.3 0 001.5-6.25 34.4 34.4 0 00-9.41-9.14A4.36 4.36 0 0085.24 16a174.51 174.51 0 01-7.45 19.59zM64.69 40.6a167.72 167.72 0 00-20.22-7.44A4.36 4.36 0 0039 36.6a33.68 33.68 0 00-.45 5.54 34 34 0 00.81 7.4 4.36 4.36 0 006.28 2.84 189.19 189.19 0 0119-8.52 1.76 1.76 0 00.05-3.26zM20 129.315c0 5-2.72 8.16-7.11 8.16-2.37 0-4.17-1-6.2-3.56l-.69-.78-6 5 .57.76c3.25 4.36 7.16 6.39 12.31 6.39 9 0 15.34-6.57 15.34-16v-28.1H20zM61.69 126.505c0 6.66-3.76 11-9.57 11-5.81 0-9.56-4.31-9.56-11v-25.32h-8.23v25.69c0 10.66 7.4 18.4 17.6 18.4 10 0 17.61-7.72 18-18.4v-25.69h-8.24zM106.83 134.095c-3.58 2.43-6.18 3.38-9.25 3.38a14.53 14.53 0 010-29c3.24 0 5.66.88 9.25 3.38l.76.53 4.78-6-.75-.62a22.18 22.18 0 00-14.22-5.1 22.33 22.33 0 100 44.65 21.53 21.53 0 0014.39-5.08l.81-.64-5-6zM145.75 137.285h-19.06v-10.72h18.3v-7.61h-18.3v-10.16h19.06v-7.61h-27.28v43.53h27.28z" | ||||
|         "M68.015 83.917c-7.723-.902-15.472-4.123-21.566-8.966-8.475-6.736-14.172-16.823-15.574-27.575C29.303 35.31 33.538 22.7 42.21 13.631 49.154 6.368 58.07 1.902 68.042.695c2.15-.26 7.524-.26 9.675 0 12.488 1.512 23.464 8.25 30.437 18.686 8.332 12.471 9.318 28.123 2.605 41.368-2.28 4.5-4.337 7.359-7.85 10.909A42.273 42.273 0 0177.613 83.92c-2.027.227-7.644.225-9.598-.003zm7.823-5.596c8.435-.415 17.446-4.678 23.683-11.205 5.976-6.254 9.35-13.723 10.181-22.537.632-6.705-1.346-14.948-5.065-21.108C98.88 13.935 89.397 7.602 78.34 5.906c-2.541-.39-8.398-.386-10.96.006C53.54 8.034 42.185 17.542 37.81 30.67c-2.807 8.426-2.421 17.267 1.11 25.444 4.877 11.297 14.959 19.41 26.977 21.709 2.136.408 6.1.755 7.377.645.325-.028 1.48-.094 2.564-.147z" | ||||
|   ); | ||||
| } | ||||
|  | ||||
| //============================================================================== | ||||
| #if JUCE_MODULE_AVAILABLE_juce_gui_extra | ||||
|  inline CodeEditorComponent::ColourScheme getDarkCodeEditorColourScheme() | ||||
|  { | ||||
|      struct Type | ||||
|      { | ||||
|          const char* name; | ||||
|          juce::uint32 colour; | ||||
|      }; | ||||
|  | ||||
|      const Type types[] = | ||||
|      { | ||||
|          { "Error",              0xffe60000 }, | ||||
|          { "Comment",            0xff72d20c }, | ||||
|          { "Keyword",            0xffee6f6f }, | ||||
|          { "Operator",           0xffc4eb19 }, | ||||
|          { "Identifier",         0xffcfcfcf }, | ||||
|          { "Integer",            0xff42c8c4 }, | ||||
|          { "Float",              0xff885500 }, | ||||
|          { "String",             0xffbc45dd }, | ||||
|          { "Bracket",            0xff058202 }, | ||||
|          { "Punctuation",        0xffcfbeff }, | ||||
|          { "Preprocessor Text",  0xfff8f631 } | ||||
|      }; | ||||
|  | ||||
|      CodeEditorComponent::ColourScheme cs; | ||||
|  | ||||
|      for (auto& t : types) | ||||
|          cs.set (t.name, Colour (t.colour)); | ||||
|  | ||||
|      return cs; | ||||
|  } | ||||
|  | ||||
|  inline CodeEditorComponent::ColourScheme getLightCodeEditorColourScheme() | ||||
|  { | ||||
|      struct Type | ||||
|      { | ||||
|          const char* name; | ||||
|          juce::uint32 colour; | ||||
|      }; | ||||
|  | ||||
|      const Type types[] = | ||||
|      { | ||||
|          { "Error",              0xffcc0000 }, | ||||
|          { "Comment",            0xff00aa00 }, | ||||
|          { "Keyword",            0xff0000cc }, | ||||
|          { "Operator",           0xff225500 }, | ||||
|          { "Identifier",         0xff000000 }, | ||||
|          { "Integer",            0xff880000 }, | ||||
|          { "Float",              0xff885500 }, | ||||
|          { "String",             0xff990099 }, | ||||
|          { "Bracket",            0xff000055 }, | ||||
|          { "Punctuation",        0xff004400 }, | ||||
|          { "Preprocessor Text",  0xff660000 } | ||||
|      }; | ||||
|  | ||||
|      CodeEditorComponent::ColourScheme cs; | ||||
|  | ||||
|      for (auto& t : types) | ||||
|          cs.set (t.name, Colour (t.colour)); | ||||
|  | ||||
|      return cs; | ||||
|  } | ||||
| #endif | ||||
|  | ||||
| //============================================================================== | ||||
| // This is basically a sawtooth wave generator - maps a value that bounces between | ||||
| // 0.0 and 1.0 at a random speed | ||||
| struct BouncingNumber | ||||
| { | ||||
|     BouncingNumber() | ||||
|         : speed (0.0004 + 0.0007 * Random::getSystemRandom().nextDouble()), | ||||
|           phase (Random::getSystemRandom().nextDouble()) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     float getValue() const | ||||
|     { | ||||
|         double v = fmod (phase + speed * Time::getMillisecondCounterHiRes(), 2.0); | ||||
|         return (float) (v >= 1.0 ? (2.0 - v) : v); | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     double speed, phase; | ||||
| }; | ||||
|  | ||||
| struct SlowerBouncingNumber  : public BouncingNumber | ||||
| { | ||||
|     SlowerBouncingNumber() | ||||
|     { | ||||
|         speed *= 0.3; | ||||
|     } | ||||
| }; | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2022 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #ifndef PIP_DEMO_UTILITIES_INCLUDED | ||||
| #define PIP_DEMO_UTILITIES_INCLUDED 1 | ||||
|  | ||||
| #include <JuceHeader.h> | ||||
|  | ||||
| //============================================================================== | ||||
| /* | ||||
|     This file contains a bunch of miscellaneous utilities that are | ||||
|     used by the various demos. | ||||
| */ | ||||
|  | ||||
| //============================================================================== | ||||
| inline Colour getRandomColour (float brightness) noexcept | ||||
| { | ||||
|     return Colour::fromHSV (Random::getSystemRandom().nextFloat(), 0.5f, brightness, 1.0f); | ||||
| } | ||||
|  | ||||
| inline Colour getRandomBrightColour() noexcept  { return getRandomColour (0.8f); } | ||||
| inline Colour getRandomDarkColour() noexcept    { return getRandomColour (0.3f); } | ||||
|  | ||||
| inline Colour getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour uiColour, Colour fallback = Colour (0xff4d4d4d)) noexcept | ||||
| { | ||||
|     if (auto* v4 = dynamic_cast<LookAndFeel_V4*> (&LookAndFeel::getDefaultLookAndFeel())) | ||||
|         return v4->getCurrentColourScheme().getUIColour (uiColour); | ||||
|  | ||||
|     return fallback; | ||||
| } | ||||
|  | ||||
| inline File getExamplesDirectory() noexcept | ||||
| { | ||||
|    #ifdef PIP_JUCE_EXAMPLES_DIRECTORY | ||||
|     MemoryOutputStream mo; | ||||
|  | ||||
|     auto success = Base64::convertFromBase64 (mo, JUCE_STRINGIFY (PIP_JUCE_EXAMPLES_DIRECTORY)); | ||||
|     ignoreUnused (success); | ||||
|     jassert (success); | ||||
|  | ||||
|     return mo.toString(); | ||||
|    #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING | ||||
|     return File { CharPointer_UTF8 { PIP_JUCE_EXAMPLES_DIRECTORY_STRING } }; | ||||
|    #else | ||||
|     auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile); | ||||
|     auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples"); | ||||
|  | ||||
|     if (exampleDir.exists()) | ||||
|         return exampleDir; | ||||
|  | ||||
|     // keep track of the number of parent directories so we don't go on endlessly | ||||
|     for (int numTries = 0; numTries < 15; ++numTries) | ||||
|     { | ||||
|         if (currentFile.getFileName() == "examples") | ||||
|             return currentFile; | ||||
|  | ||||
|         const auto sibling = currentFile.getSiblingFile ("examples"); | ||||
|  | ||||
|         if (sibling.exists()) | ||||
|             return sibling; | ||||
|  | ||||
|         currentFile = currentFile.getParentDirectory(); | ||||
|     } | ||||
|  | ||||
|     return currentFile; | ||||
|    #endif | ||||
| } | ||||
|  | ||||
| inline std::unique_ptr<InputStream> createAssetInputStream (const char* resourcePath) | ||||
| { | ||||
|   #if JUCE_ANDROID | ||||
|     ZipFile apkZip (File::getSpecialLocation (File::invokedExecutableFile)); | ||||
|     return std::unique_ptr<InputStream> (apkZip.createStreamForEntry (apkZip.getIndexOfFileName ("assets/" + String (resourcePath)))); | ||||
|   #else | ||||
|    #if JUCE_IOS | ||||
|     auto assetsDir = File::getSpecialLocation (File::currentExecutableFile) | ||||
|                           .getParentDirectory().getChildFile ("Assets"); | ||||
|    #elif JUCE_MAC | ||||
|     auto assetsDir = File::getSpecialLocation (File::currentExecutableFile) | ||||
|                           .getParentDirectory().getParentDirectory().getChildFile ("Resources").getChildFile ("Assets"); | ||||
|  | ||||
|     if (! assetsDir.exists()) | ||||
|         assetsDir = getExamplesDirectory().getChildFile ("Assets"); | ||||
|    #else | ||||
|     auto assetsDir = getExamplesDirectory().getChildFile ("Assets"); | ||||
|    #endif | ||||
|  | ||||
|     auto resourceFile = assetsDir.getChildFile (resourcePath); | ||||
|     jassert (resourceFile.existsAsFile()); | ||||
|  | ||||
|     return resourceFile.createInputStream(); | ||||
|   #endif | ||||
| } | ||||
|  | ||||
| inline Image getImageFromAssets (const char* assetName) | ||||
| { | ||||
|     auto hashCode = (String (assetName) + "@juce_demo_assets").hashCode64(); | ||||
|     auto img = ImageCache::getFromHashCode (hashCode); | ||||
|  | ||||
|     if (img.isNull()) | ||||
|     { | ||||
|         std::unique_ptr<InputStream> juceIconStream (createAssetInputStream (assetName)); | ||||
|  | ||||
|         if (juceIconStream == nullptr) | ||||
|             return {}; | ||||
|  | ||||
|         img = ImageFileFormat::loadFrom (*juceIconStream); | ||||
|  | ||||
|         ImageCache::addImageToCache (img, hashCode); | ||||
|     } | ||||
|  | ||||
|     return img; | ||||
| } | ||||
|  | ||||
| inline String loadEntireAssetIntoString (const char* assetName) | ||||
| { | ||||
|     std::unique_ptr<InputStream> input (createAssetInputStream (assetName)); | ||||
|  | ||||
|     if (input == nullptr) | ||||
|         return {}; | ||||
|  | ||||
|     return input->readString(); | ||||
| } | ||||
|  | ||||
| //============================================================================== | ||||
| inline Path getJUCELogoPath() | ||||
| { | ||||
|     return Drawable::parseSVGPath ( | ||||
|         "M72.87 84.28A42.36 42.36 0 0130.4 42.14a42.48 42.48 0 0184.95 0 42.36 42.36 0 01-42.48 42.14zm0-78.67A36.74 36.74 0 0036 42.14a36.88 36.88 0 0073.75 0A36.75 36.75 0 0072.87 5.61z" | ||||
|         "M77.62 49.59a177.77 177.77 0 008.74 18.93A4.38 4.38 0 0092.69 70a34.5 34.5 0 008.84-9 4.3 4.3 0 00-2.38-6.49A176.73 176.73 0 0180 47.32a1.78 1.78 0 00-2.38 2.27zM81.05 44.27a169.68 169.68 0 0020.13 7.41 4.39 4.39 0 005.52-3.41 34.42 34.42 0 00.55-6.13 33.81 33.81 0 00-.67-6.72 4.37 4.37 0 00-6.31-3A192.32 192.32 0 0181.1 41a1.76 1.76 0 00-.05 3.27zM74.47 50.44a1.78 1.78 0 00-3.29 0 165.54 165.54 0 00-7.46 19.89 4.33 4.33 0 003.47 5.48 35.49 35.49 0 005.68.46 34.44 34.44 0 007.13-.79 4.32 4.32 0 003-6.25 187.83 187.83 0 01-8.53-18.79zM71.59 34.12a1.78 1.78 0 003.29.05 163.9 163.9 0 007.52-20.11A4.34 4.34 0 0079 8.59a35.15 35.15 0 00-13.06.17 4.32 4.32 0 00-3 6.26 188.41 188.41 0 018.65 19.1zM46.32 30.3a176.2 176.2 0 0120 7.48 1.78 1.78 0 002.37-2.28 180.72 180.72 0 00-9.13-19.84 4.38 4.38 0 00-6.33-1.47 34.27 34.27 0 00-9.32 9.65 4.31 4.31 0 002.41 6.46zM68.17 49.18a1.77 1.77 0 00-2.29-2.34 181.71 181.71 0 00-19.51 8.82A4.3 4.3 0 0044.91 62a34.36 34.36 0 009.42 8.88 4.36 4.36 0 006.5-2.38 175.11 175.11 0 017.34-19.32zM77.79 35.59a1.78 1.78 0 002.3 2.35 182.51 182.51 0 0019.6-8.88 4.3 4.3 0 001.5-6.25 34.4 34.4 0 00-9.41-9.14A4.36 4.36 0 0085.24 16a174.51 174.51 0 01-7.45 19.59zM64.69 40.6a167.72 167.72 0 00-20.22-7.44A4.36 4.36 0 0039 36.6a33.68 33.68 0 00-.45 5.54 34 34 0 00.81 7.4 4.36 4.36 0 006.28 2.84 189.19 189.19 0 0119-8.52 1.76 1.76 0 00.05-3.26zM20 129.315c0 5-2.72 8.16-7.11 8.16-2.37 0-4.17-1-6.2-3.56l-.69-.78-6 5 .57.76c3.25 4.36 7.16 6.39 12.31 6.39 9 0 15.34-6.57 15.34-16v-28.1H20zM61.69 126.505c0 6.66-3.76 11-9.57 11-5.81 0-9.56-4.31-9.56-11v-25.32h-8.23v25.69c0 10.66 7.4 18.4 17.6 18.4 10 0 17.61-7.72 18-18.4v-25.69h-8.24zM106.83 134.095c-3.58 2.43-6.18 3.38-9.25 3.38a14.53 14.53 0 010-29c3.24 0 5.66.88 9.25 3.38l.76.53 4.78-6-.75-.62a22.18 22.18 0 00-14.22-5.1 22.33 22.33 0 100 44.65 21.53 21.53 0 0014.39-5.08l.81-.64-5-6zM145.75 137.285h-19.06v-10.72h18.3v-7.61h-18.3v-10.16h19.06v-7.61h-27.28v43.53h27.28z" | ||||
|         "M68.015 83.917c-7.723-.902-15.472-4.123-21.566-8.966-8.475-6.736-14.172-16.823-15.574-27.575C29.303 35.31 33.538 22.7 42.21 13.631 49.154 6.368 58.07 1.902 68.042.695c2.15-.26 7.524-.26 9.675 0 12.488 1.512 23.464 8.25 30.437 18.686 8.332 12.471 9.318 28.123 2.605 41.368-2.28 4.5-4.337 7.359-7.85 10.909A42.273 42.273 0 0177.613 83.92c-2.027.227-7.644.225-9.598-.003zm7.823-5.596c8.435-.415 17.446-4.678 23.683-11.205 5.976-6.254 9.35-13.723 10.181-22.537.632-6.705-1.346-14.948-5.065-21.108C98.88 13.935 89.397 7.602 78.34 5.906c-2.541-.39-8.398-.386-10.96.006C53.54 8.034 42.185 17.542 37.81 30.67c-2.807 8.426-2.421 17.267 1.11 25.444 4.877 11.297 14.959 19.41 26.977 21.709 2.136.408 6.1.755 7.377.645.325-.028 1.48-.094 2.564-.147z" | ||||
|   ); | ||||
| } | ||||
|  | ||||
| //============================================================================== | ||||
| #if JUCE_MODULE_AVAILABLE_juce_gui_extra | ||||
|  inline CodeEditorComponent::ColourScheme getDarkCodeEditorColourScheme() | ||||
|  { | ||||
|      struct Type | ||||
|      { | ||||
|          const char* name; | ||||
|          juce::uint32 colour; | ||||
|      }; | ||||
|  | ||||
|      const Type types[] = | ||||
|      { | ||||
|          { "Error",              0xffe60000 }, | ||||
|          { "Comment",            0xff72d20c }, | ||||
|          { "Keyword",            0xffee6f6f }, | ||||
|          { "Operator",           0xffc4eb19 }, | ||||
|          { "Identifier",         0xffcfcfcf }, | ||||
|          { "Integer",            0xff42c8c4 }, | ||||
|          { "Float",              0xff885500 }, | ||||
|          { "String",             0xffbc45dd }, | ||||
|          { "Bracket",            0xff058202 }, | ||||
|          { "Punctuation",        0xffcfbeff }, | ||||
|          { "Preprocessor Text",  0xfff8f631 } | ||||
|      }; | ||||
|  | ||||
|      CodeEditorComponent::ColourScheme cs; | ||||
|  | ||||
|      for (auto& t : types) | ||||
|          cs.set (t.name, Colour (t.colour)); | ||||
|  | ||||
|      return cs; | ||||
|  } | ||||
|  | ||||
|  inline CodeEditorComponent::ColourScheme getLightCodeEditorColourScheme() | ||||
|  { | ||||
|      struct Type | ||||
|      { | ||||
|          const char* name; | ||||
|          juce::uint32 colour; | ||||
|      }; | ||||
|  | ||||
|      const Type types[] = | ||||
|      { | ||||
|          { "Error",              0xffcc0000 }, | ||||
|          { "Comment",            0xff00aa00 }, | ||||
|          { "Keyword",            0xff0000cc }, | ||||
|          { "Operator",           0xff225500 }, | ||||
|          { "Identifier",         0xff000000 }, | ||||
|          { "Integer",            0xff880000 }, | ||||
|          { "Float",              0xff885500 }, | ||||
|          { "String",             0xff990099 }, | ||||
|          { "Bracket",            0xff000055 }, | ||||
|          { "Punctuation",        0xff004400 }, | ||||
|          { "Preprocessor Text",  0xff660000 } | ||||
|      }; | ||||
|  | ||||
|      CodeEditorComponent::ColourScheme cs; | ||||
|  | ||||
|      for (auto& t : types) | ||||
|          cs.set (t.name, Colour (t.colour)); | ||||
|  | ||||
|      return cs; | ||||
|  } | ||||
| #endif | ||||
|  | ||||
| //============================================================================== | ||||
| // This is basically a sawtooth wave generator - maps a value that bounces between | ||||
| // 0.0 and 1.0 at a random speed | ||||
| struct BouncingNumber | ||||
| { | ||||
|     BouncingNumber() | ||||
|         : speed (0.0004 + 0.0007 * Random::getSystemRandom().nextDouble()), | ||||
|           phase (Random::getSystemRandom().nextDouble()) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     float getValue() const | ||||
|     { | ||||
|         double v = fmod (phase + speed * Time::getMillisecondCounterHiRes(), 2.0); | ||||
|         return (float) (v >= 1.0 ? (2.0 - v) : v); | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     double speed, phase; | ||||
| }; | ||||
|  | ||||
| struct SlowerBouncingNumber  : public BouncingNumber | ||||
| { | ||||
|     SlowerBouncingNumber() | ||||
|     { | ||||
|         speed *= 0.3; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif   // PIP_DEMO_UTILITIES_INCLUDED | ||||
|   | ||||
| @@ -1,365 +1,365 @@ | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2020 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
|  | ||||
| //============================================================================== | ||||
| /** | ||||
|     This is a quick-and-dirty parser for the 3D OBJ file format. | ||||
|  | ||||
|     Just call load() and if there aren't any errors, the 'shapes' array should | ||||
|     be filled with all the shape objects that were loaded from the file. | ||||
| */ | ||||
| class WavefrontObjFile | ||||
| { | ||||
| public: | ||||
|     WavefrontObjFile() {} | ||||
|  | ||||
|     Result load (const String& objFileContent) | ||||
|     { | ||||
|         shapes.clear(); | ||||
|         return parseObjFile (StringArray::fromLines (objFileContent)); | ||||
|     } | ||||
|  | ||||
|     Result load (const File& file) | ||||
|     { | ||||
|         sourceFile = file; | ||||
|         return load (file.loadFileAsString()); | ||||
|     } | ||||
|  | ||||
|     //============================================================================== | ||||
|     typedef juce::uint32 Index; | ||||
|  | ||||
|     struct Vertex        { float x, y, z; }; | ||||
|     struct TextureCoord  { float x, y;    }; | ||||
|  | ||||
|     struct Mesh | ||||
|     { | ||||
|         Array<Vertex> vertices, normals; | ||||
|         Array<TextureCoord> textureCoords; | ||||
|         Array<Index> indices; | ||||
|     }; | ||||
|  | ||||
|     struct Material | ||||
|     { | ||||
|         Material() noexcept | ||||
|         { | ||||
|             zerostruct (ambient); | ||||
|             zerostruct (diffuse); | ||||
|             zerostruct (specular); | ||||
|             zerostruct (transmittance); | ||||
|             zerostruct (emission); | ||||
|         } | ||||
|  | ||||
|         String name; | ||||
|  | ||||
|         Vertex ambient, diffuse, specular, transmittance, emission; | ||||
|         float shininess = 1.0f, refractiveIndex = 0.0f; | ||||
|  | ||||
|         String ambientTextureName, diffuseTextureName, | ||||
|                specularTextureName, normalTextureName; | ||||
|  | ||||
|         StringPairArray parameters; | ||||
|     }; | ||||
|  | ||||
|     struct Shape | ||||
|     { | ||||
|         String name; | ||||
|         Mesh mesh; | ||||
|         Material material; | ||||
|     }; | ||||
|  | ||||
|     OwnedArray<Shape> shapes; | ||||
|  | ||||
| private: | ||||
|     //============================================================================== | ||||
|     File sourceFile; | ||||
|  | ||||
|     struct TripleIndex | ||||
|     { | ||||
|         TripleIndex() noexcept {} | ||||
|  | ||||
|         bool operator< (const TripleIndex& other) const noexcept | ||||
|         { | ||||
|             if (this == &other) | ||||
|                 return false; | ||||
|  | ||||
|             if (vertexIndex != other.vertexIndex) | ||||
|                 return vertexIndex < other.vertexIndex; | ||||
|  | ||||
|             if (textureIndex != other.textureIndex) | ||||
|                 return textureIndex < other.textureIndex; | ||||
|  | ||||
|             return normalIndex < other.normalIndex; | ||||
|         } | ||||
|  | ||||
|         int vertexIndex = -1, textureIndex = -1, normalIndex = -1; | ||||
|     }; | ||||
|  | ||||
|     struct IndexMap | ||||
|     { | ||||
|         std::map<TripleIndex, Index> map; | ||||
|  | ||||
|         Index getIndexFor (TripleIndex i, Mesh& newMesh, const Mesh& srcMesh) | ||||
|         { | ||||
|             const std::map<TripleIndex, Index>::iterator it (map.find (i)); | ||||
|  | ||||
|             if (it != map.end()) | ||||
|                 return it->second; | ||||
|  | ||||
|             auto index = (Index) newMesh.vertices.size(); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.vertexIndex, srcMesh.vertices.size())) | ||||
|                 newMesh.vertices.add (srcMesh.vertices.getReference (i.vertexIndex)); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.normalIndex, srcMesh.normals.size())) | ||||
|                 newMesh.normals.add (srcMesh.normals.getReference (i.normalIndex)); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.textureIndex, srcMesh.textureCoords.size())) | ||||
|                 newMesh.textureCoords.add (srcMesh.textureCoords.getReference (i.textureIndex)); | ||||
|  | ||||
|             map[i] = index; | ||||
|             return index; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     static float parseFloat (String::CharPointerType& t) | ||||
|     { | ||||
|         t.incrementToEndOfWhitespace(); | ||||
|         return (float) CharacterFunctions::readDoubleValue (t); | ||||
|     } | ||||
|  | ||||
|     static Vertex parseVertex (String::CharPointerType t) | ||||
|     { | ||||
|         Vertex v; | ||||
|         v.x = parseFloat (t); | ||||
|         v.y = parseFloat (t); | ||||
|         v.z = parseFloat (t); | ||||
|         return v; | ||||
|     } | ||||
|  | ||||
|     static TextureCoord parseTextureCoord (String::CharPointerType t) | ||||
|     { | ||||
|         TextureCoord tc; | ||||
|         tc.x = parseFloat (t); | ||||
|         tc.y = parseFloat (t); | ||||
|         return tc; | ||||
|     } | ||||
|  | ||||
|     static bool matchToken (String::CharPointerType& t, const char* token) | ||||
|     { | ||||
|         auto len = (int) strlen (token); | ||||
|  | ||||
|         if (CharacterFunctions::compareUpTo (CharPointer_ASCII (token), t, len) == 0) | ||||
|         { | ||||
|             auto end = t + len; | ||||
|  | ||||
|             if (end.isEmpty() || end.isWhitespace()) | ||||
|             { | ||||
|                 t = end.findEndOfWhitespace(); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     struct Face | ||||
|     { | ||||
|         Face (String::CharPointerType t) | ||||
|         { | ||||
|             while (! t.isEmpty()) | ||||
|                 triples.add (parseTriple (t)); | ||||
|         } | ||||
|  | ||||
|         Array<TripleIndex> triples; | ||||
|  | ||||
|         void addIndices (Mesh& newMesh, const Mesh& srcMesh, IndexMap& indexMap) | ||||
|         { | ||||
|             TripleIndex i0 (triples[0]), i1, i2 (triples[1]); | ||||
|  | ||||
|             for (auto i = 2; i < triples.size(); ++i) | ||||
|             { | ||||
|                 i1 = i2; | ||||
|                 i2 = triples.getReference (i); | ||||
|  | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i0, newMesh, srcMesh)); | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i1, newMesh, srcMesh)); | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i2, newMesh, srcMesh)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static TripleIndex parseTriple (String::CharPointerType& t) | ||||
|         { | ||||
|             TripleIndex i; | ||||
|  | ||||
|             t.incrementToEndOfWhitespace(); | ||||
|             i.vertexIndex = t.getIntValue32() - 1; | ||||
|             t = findEndOfFaceToken (t); | ||||
|  | ||||
|             if (t.isEmpty() || t.getAndAdvance() != '/') | ||||
|                 return i; | ||||
|  | ||||
|             if (*t == '/') | ||||
|             { | ||||
|                 ++t; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 i.textureIndex = t.getIntValue32() - 1; | ||||
|                 t = findEndOfFaceToken (t); | ||||
|  | ||||
|                 if (t.isEmpty() || t.getAndAdvance() != '/') | ||||
|                     return i; | ||||
|             } | ||||
|  | ||||
|             i.normalIndex = t.getIntValue32() - 1; | ||||
|             t = findEndOfFaceToken (t); | ||||
|             return i; | ||||
|         } | ||||
|  | ||||
|         static String::CharPointerType findEndOfFaceToken (String::CharPointerType t) noexcept | ||||
|         { | ||||
|             return CharacterFunctions::findEndOfToken (t, CharPointer_ASCII ("/ \t"), String().getCharPointer()); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     static Shape* parseFaceGroup (const Mesh& srcMesh, | ||||
|                                   Array<Face>& faceGroup, | ||||
|                                   const Material& material, | ||||
|                                   const String& name) | ||||
|     { | ||||
|         if (faceGroup.size() == 0) | ||||
|             return nullptr; | ||||
|  | ||||
|         std::unique_ptr<Shape> shape (new Shape()); | ||||
|         shape->name = name; | ||||
|         shape->material = material; | ||||
|  | ||||
|         IndexMap indexMap; | ||||
|  | ||||
|         for (auto& f : faceGroup) | ||||
|             f.addIndices (shape->mesh, srcMesh, indexMap); | ||||
|  | ||||
|         return shape.release(); | ||||
|     } | ||||
|  | ||||
|     Result parseObjFile (const StringArray& lines) | ||||
|     { | ||||
|         Mesh mesh; | ||||
|         Array<Face> faceGroup; | ||||
|  | ||||
|         Array<Material> knownMaterials; | ||||
|         Material lastMaterial; | ||||
|         String lastName; | ||||
|  | ||||
|         for (auto lineNum = 0; lineNum < lines.size(); ++lineNum) | ||||
|         { | ||||
|             auto l = lines[lineNum].getCharPointer().findEndOfWhitespace(); | ||||
|  | ||||
|             if (matchToken (l, "v"))    { mesh.vertices     .add (parseVertex (l));       continue; } | ||||
|             if (matchToken (l, "vn"))   { mesh.normals      .add (parseVertex (l));       continue; } | ||||
|             if (matchToken (l, "vt"))   { mesh.textureCoords.add (parseTextureCoord (l)); continue; } | ||||
|             if (matchToken (l, "f"))    { faceGroup         .add (Face (l));              continue; } | ||||
|  | ||||
|             if (matchToken (l, "usemtl")) | ||||
|             { | ||||
|                 auto name = String (l).trim(); | ||||
|  | ||||
|                 for (auto i = knownMaterials.size(); --i >= 0;) | ||||
|                 { | ||||
|                     if (knownMaterials.getReference (i).name == name) | ||||
|                     { | ||||
|                         lastMaterial = knownMaterials.getReference (i); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (matchToken (l, "mtllib")) | ||||
|             { | ||||
|                 auto r = parseMaterial (knownMaterials, String (l).trim()); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (matchToken (l, "g") || matchToken (l, "o")) | ||||
|             { | ||||
|                 if (auto* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName)) | ||||
|                     shapes.add (shape); | ||||
|  | ||||
|                 faceGroup.clear(); | ||||
|                 lastName = StringArray::fromTokens (l, " \t", "")[0]; | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (auto* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName)) | ||||
|             shapes.add (shape); | ||||
|  | ||||
|         return Result::ok(); | ||||
|     } | ||||
|  | ||||
|     Result parseMaterial (Array<Material>& materials, const String& filename) | ||||
|     { | ||||
|         jassert (sourceFile.exists()); | ||||
|         auto f = sourceFile.getSiblingFile (filename); | ||||
|  | ||||
|         if (! f.exists()) | ||||
|             return Result::fail ("Cannot open file: " + filename); | ||||
|  | ||||
|         auto lines = StringArray::fromLines (f.loadFileAsString()); | ||||
|  | ||||
|         materials.clear(); | ||||
|         Material material; | ||||
|  | ||||
|         for (auto line : lines) | ||||
|         { | ||||
|             auto l = line.getCharPointer().findEndOfWhitespace(); | ||||
|  | ||||
|             if (matchToken (l, "newmtl"))   { materials.add (material); material.name = String (l).trim(); continue; } | ||||
|  | ||||
|             if (matchToken (l, "Ka"))       { material.ambient         = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Kd"))       { material.diffuse         = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ks"))       { material.specular        = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Kt"))       { material.transmittance   = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ke"))       { material.emission        = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ni"))       { material.refractiveIndex = parseFloat (l);  continue; } | ||||
|             if (matchToken (l, "Ns"))       { material.shininess       = parseFloat (l);  continue; } | ||||
|  | ||||
|             if (matchToken (l, "map_Ka"))   { material.ambientTextureName  = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Kd"))   { material.diffuseTextureName  = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Ks"))   { material.specularTextureName = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Ns"))   { material.normalTextureName   = String (l).trim(); continue; } | ||||
|  | ||||
|             auto tokens = StringArray::fromTokens (l, " \t", ""); | ||||
|  | ||||
|             if (tokens.size() >= 2) | ||||
|                 material.parameters.set (tokens[0].trim(), tokens[1].trim()); | ||||
|         } | ||||
|  | ||||
|         materials.add (material); | ||||
|         return Result::ok(); | ||||
|     } | ||||
|  | ||||
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavefrontObjFile) | ||||
| }; | ||||
| /* | ||||
|   ============================================================================== | ||||
|  | ||||
|    This file is part of the JUCE examples. | ||||
|    Copyright (c) 2022 - Raw Material Software Limited | ||||
|  | ||||
|    The code included in this file is provided under the terms of the ISC license | ||||
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission | ||||
|    To use, copy, modify, and/or distribute this software for any purpose with or | ||||
|    without fee is hereby granted provided that the above copyright notice and | ||||
|    this permission notice appear in all copies. | ||||
|  | ||||
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, | ||||
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR | ||||
|    PURPOSE, ARE DISCLAIMED. | ||||
|  | ||||
|   ============================================================================== | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
|  | ||||
| //============================================================================== | ||||
| /** | ||||
|     This is a quick-and-dirty parser for the 3D OBJ file format. | ||||
|  | ||||
|     Just call load() and if there aren't any errors, the 'shapes' array should | ||||
|     be filled with all the shape objects that were loaded from the file. | ||||
| */ | ||||
| class WavefrontObjFile | ||||
| { | ||||
| public: | ||||
|     WavefrontObjFile() {} | ||||
|  | ||||
|     Result load (const String& objFileContent) | ||||
|     { | ||||
|         shapes.clear(); | ||||
|         return parseObjFile (StringArray::fromLines (objFileContent)); | ||||
|     } | ||||
|  | ||||
|     Result load (const File& file) | ||||
|     { | ||||
|         sourceFile = file; | ||||
|         return load (file.loadFileAsString()); | ||||
|     } | ||||
|  | ||||
|     //============================================================================== | ||||
|     typedef juce::uint32 Index; | ||||
|  | ||||
|     struct Vertex        { float x, y, z; }; | ||||
|     struct TextureCoord  { float x, y;    }; | ||||
|  | ||||
|     struct Mesh | ||||
|     { | ||||
|         Array<Vertex> vertices, normals; | ||||
|         Array<TextureCoord> textureCoords; | ||||
|         Array<Index> indices; | ||||
|     }; | ||||
|  | ||||
|     struct Material | ||||
|     { | ||||
|         Material() noexcept | ||||
|         { | ||||
|             zerostruct (ambient); | ||||
|             zerostruct (diffuse); | ||||
|             zerostruct (specular); | ||||
|             zerostruct (transmittance); | ||||
|             zerostruct (emission); | ||||
|         } | ||||
|  | ||||
|         String name; | ||||
|  | ||||
|         Vertex ambient, diffuse, specular, transmittance, emission; | ||||
|         float shininess = 1.0f, refractiveIndex = 0.0f; | ||||
|  | ||||
|         String ambientTextureName, diffuseTextureName, | ||||
|                specularTextureName, normalTextureName; | ||||
|  | ||||
|         StringPairArray parameters; | ||||
|     }; | ||||
|  | ||||
|     struct Shape | ||||
|     { | ||||
|         String name; | ||||
|         Mesh mesh; | ||||
|         Material material; | ||||
|     }; | ||||
|  | ||||
|     OwnedArray<Shape> shapes; | ||||
|  | ||||
| private: | ||||
|     //============================================================================== | ||||
|     File sourceFile; | ||||
|  | ||||
|     struct TripleIndex | ||||
|     { | ||||
|         TripleIndex() noexcept {} | ||||
|  | ||||
|         bool operator< (const TripleIndex& other) const noexcept | ||||
|         { | ||||
|             if (this == &other) | ||||
|                 return false; | ||||
|  | ||||
|             if (vertexIndex != other.vertexIndex) | ||||
|                 return vertexIndex < other.vertexIndex; | ||||
|  | ||||
|             if (textureIndex != other.textureIndex) | ||||
|                 return textureIndex < other.textureIndex; | ||||
|  | ||||
|             return normalIndex < other.normalIndex; | ||||
|         } | ||||
|  | ||||
|         int vertexIndex = -1, textureIndex = -1, normalIndex = -1; | ||||
|     }; | ||||
|  | ||||
|     struct IndexMap | ||||
|     { | ||||
|         std::map<TripleIndex, Index> map; | ||||
|  | ||||
|         Index getIndexFor (TripleIndex i, Mesh& newMesh, const Mesh& srcMesh) | ||||
|         { | ||||
|             const std::map<TripleIndex, Index>::iterator it (map.find (i)); | ||||
|  | ||||
|             if (it != map.end()) | ||||
|                 return it->second; | ||||
|  | ||||
|             auto index = (Index) newMesh.vertices.size(); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.vertexIndex, srcMesh.vertices.size())) | ||||
|                 newMesh.vertices.add (srcMesh.vertices.getReference (i.vertexIndex)); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.normalIndex, srcMesh.normals.size())) | ||||
|                 newMesh.normals.add (srcMesh.normals.getReference (i.normalIndex)); | ||||
|  | ||||
|             if (isPositiveAndBelow (i.textureIndex, srcMesh.textureCoords.size())) | ||||
|                 newMesh.textureCoords.add (srcMesh.textureCoords.getReference (i.textureIndex)); | ||||
|  | ||||
|             map[i] = index; | ||||
|             return index; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     static float parseFloat (String::CharPointerType& t) | ||||
|     { | ||||
|         t.incrementToEndOfWhitespace(); | ||||
|         return (float) CharacterFunctions::readDoubleValue (t); | ||||
|     } | ||||
|  | ||||
|     static Vertex parseVertex (String::CharPointerType t) | ||||
|     { | ||||
|         Vertex v; | ||||
|         v.x = parseFloat (t); | ||||
|         v.y = parseFloat (t); | ||||
|         v.z = parseFloat (t); | ||||
|         return v; | ||||
|     } | ||||
|  | ||||
|     static TextureCoord parseTextureCoord (String::CharPointerType t) | ||||
|     { | ||||
|         TextureCoord tc; | ||||
|         tc.x = parseFloat (t); | ||||
|         tc.y = parseFloat (t); | ||||
|         return tc; | ||||
|     } | ||||
|  | ||||
|     static bool matchToken (String::CharPointerType& t, const char* token) | ||||
|     { | ||||
|         auto len = (int) strlen (token); | ||||
|  | ||||
|         if (CharacterFunctions::compareUpTo (CharPointer_ASCII (token), t, len) == 0) | ||||
|         { | ||||
|             auto end = t + len; | ||||
|  | ||||
|             if (end.isEmpty() || end.isWhitespace()) | ||||
|             { | ||||
|                 t = end.findEndOfWhitespace(); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     struct Face | ||||
|     { | ||||
|         Face (String::CharPointerType t) | ||||
|         { | ||||
|             while (! t.isEmpty()) | ||||
|                 triples.add (parseTriple (t)); | ||||
|         } | ||||
|  | ||||
|         Array<TripleIndex> triples; | ||||
|  | ||||
|         void addIndices (Mesh& newMesh, const Mesh& srcMesh, IndexMap& indexMap) | ||||
|         { | ||||
|             TripleIndex i0 (triples[0]), i1, i2 (triples[1]); | ||||
|  | ||||
|             for (auto i = 2; i < triples.size(); ++i) | ||||
|             { | ||||
|                 i1 = i2; | ||||
|                 i2 = triples.getReference (i); | ||||
|  | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i0, newMesh, srcMesh)); | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i1, newMesh, srcMesh)); | ||||
|                 newMesh.indices.add (indexMap.getIndexFor (i2, newMesh, srcMesh)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static TripleIndex parseTriple (String::CharPointerType& t) | ||||
|         { | ||||
|             TripleIndex i; | ||||
|  | ||||
|             t.incrementToEndOfWhitespace(); | ||||
|             i.vertexIndex = t.getIntValue32() - 1; | ||||
|             t = findEndOfFaceToken (t); | ||||
|  | ||||
|             if (t.isEmpty() || t.getAndAdvance() != '/') | ||||
|                 return i; | ||||
|  | ||||
|             if (*t == '/') | ||||
|             { | ||||
|                 ++t; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 i.textureIndex = t.getIntValue32() - 1; | ||||
|                 t = findEndOfFaceToken (t); | ||||
|  | ||||
|                 if (t.isEmpty() || t.getAndAdvance() != '/') | ||||
|                     return i; | ||||
|             } | ||||
|  | ||||
|             i.normalIndex = t.getIntValue32() - 1; | ||||
|             t = findEndOfFaceToken (t); | ||||
|             return i; | ||||
|         } | ||||
|  | ||||
|         static String::CharPointerType findEndOfFaceToken (String::CharPointerType t) noexcept | ||||
|         { | ||||
|             return CharacterFunctions::findEndOfToken (t, CharPointer_ASCII ("/ \t"), String().getCharPointer()); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     static Shape* parseFaceGroup (const Mesh& srcMesh, | ||||
|                                   Array<Face>& faceGroup, | ||||
|                                   const Material& material, | ||||
|                                   const String& name) | ||||
|     { | ||||
|         if (faceGroup.size() == 0) | ||||
|             return nullptr; | ||||
|  | ||||
|         std::unique_ptr<Shape> shape (new Shape()); | ||||
|         shape->name = name; | ||||
|         shape->material = material; | ||||
|  | ||||
|         IndexMap indexMap; | ||||
|  | ||||
|         for (auto& f : faceGroup) | ||||
|             f.addIndices (shape->mesh, srcMesh, indexMap); | ||||
|  | ||||
|         return shape.release(); | ||||
|     } | ||||
|  | ||||
|     Result parseObjFile (const StringArray& lines) | ||||
|     { | ||||
|         Mesh mesh; | ||||
|         Array<Face> faceGroup; | ||||
|  | ||||
|         Array<Material> knownMaterials; | ||||
|         Material lastMaterial; | ||||
|         String lastName; | ||||
|  | ||||
|         for (auto lineNum = 0; lineNum < lines.size(); ++lineNum) | ||||
|         { | ||||
|             auto l = lines[lineNum].getCharPointer().findEndOfWhitespace(); | ||||
|  | ||||
|             if (matchToken (l, "v"))    { mesh.vertices     .add (parseVertex (l));       continue; } | ||||
|             if (matchToken (l, "vn"))   { mesh.normals      .add (parseVertex (l));       continue; } | ||||
|             if (matchToken (l, "vt"))   { mesh.textureCoords.add (parseTextureCoord (l)); continue; } | ||||
|             if (matchToken (l, "f"))    { faceGroup         .add (Face (l));              continue; } | ||||
|  | ||||
|             if (matchToken (l, "usemtl")) | ||||
|             { | ||||
|                 auto name = String (l).trim(); | ||||
|  | ||||
|                 for (auto i = knownMaterials.size(); --i >= 0;) | ||||
|                 { | ||||
|                     if (knownMaterials.getReference (i).name == name) | ||||
|                     { | ||||
|                         lastMaterial = knownMaterials.getReference (i); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (matchToken (l, "mtllib")) | ||||
|             { | ||||
|                 auto r = parseMaterial (knownMaterials, String (l).trim()); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (matchToken (l, "g") || matchToken (l, "o")) | ||||
|             { | ||||
|                 if (auto* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName)) | ||||
|                     shapes.add (shape); | ||||
|  | ||||
|                 faceGroup.clear(); | ||||
|                 lastName = StringArray::fromTokens (l, " \t", "")[0]; | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (auto* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName)) | ||||
|             shapes.add (shape); | ||||
|  | ||||
|         return Result::ok(); | ||||
|     } | ||||
|  | ||||
|     Result parseMaterial (Array<Material>& materials, const String& filename) | ||||
|     { | ||||
|         jassert (sourceFile.exists()); | ||||
|         auto f = sourceFile.getSiblingFile (filename); | ||||
|  | ||||
|         if (! f.exists()) | ||||
|             return Result::fail ("Cannot open file: " + filename); | ||||
|  | ||||
|         auto lines = StringArray::fromLines (f.loadFileAsString()); | ||||
|  | ||||
|         materials.clear(); | ||||
|         Material material; | ||||
|  | ||||
|         for (auto line : lines) | ||||
|         { | ||||
|             auto l = line.getCharPointer().findEndOfWhitespace(); | ||||
|  | ||||
|             if (matchToken (l, "newmtl"))   { materials.add (material); material.name = String (l).trim(); continue; } | ||||
|  | ||||
|             if (matchToken (l, "Ka"))       { material.ambient         = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Kd"))       { material.diffuse         = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ks"))       { material.specular        = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Kt"))       { material.transmittance   = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ke"))       { material.emission        = parseVertex (l); continue; } | ||||
|             if (matchToken (l, "Ni"))       { material.refractiveIndex = parseFloat (l);  continue; } | ||||
|             if (matchToken (l, "Ns"))       { material.shininess       = parseFloat (l);  continue; } | ||||
|  | ||||
|             if (matchToken (l, "map_Ka"))   { material.ambientTextureName  = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Kd"))   { material.diffuseTextureName  = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Ks"))   { material.specularTextureName = String (l).trim(); continue; } | ||||
|             if (matchToken (l, "map_Ns"))   { material.normalTextureName   = String (l).trim(); continue; } | ||||
|  | ||||
|             auto tokens = StringArray::fromTokens (l, " \t", ""); | ||||
|  | ||||
|             if (tokens.size() >= 2) | ||||
|                 material.parameters.set (tokens[0].trim(), tokens[1].trim()); | ||||
|         } | ||||
|  | ||||
|         materials.add (material); | ||||
|         return Result::ok(); | ||||
|     } | ||||
|  | ||||
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavefrontObjFile) | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nikolai Rodionov
						Nikolai Rodionov