topical media & game development

talk show tell print

lib-game-delta3d-sdk-examples-testPhysics-testphysics.cpp / cpp



  /* -*-c++-*-
   * testNetwork - testphysics (.h & .cpp) - Using 'The MIT License'
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  include <dtABC/application.h>
  include <dtABC/labelactor.h>
  include <dtCore/object.h>
  include <dtCore/odebodywrap.h>
  include <dtCore/odecontroller.h>
  include <dtCore/globals.h>
  include <dtCore/orbitmotionmodel.h>
  include <dtCore/scene.h>
  include <dtCore/camera.h>
  include <dtCore/system.h>
  include <dtCore/transform.h>
  include <dtUtil/mathdefines.h>
  include <ode/ode.h>
  include <cassert>
  include <queue>
  include <osgGA/GUIEventAdapter>
  
  using namespace dtCore;
  using namespace dtABC;
  using namespace dtUtil;
  
  class Updater : public Base
  {
  
  public:
     Updater(Scene* scene)
        : mScene(scene)
     {
        assert(mScene.valid());
        AddSender(mScene.get());
     }
  protected:
     virtual ~Updater()
     {
        RemoveSender(mScene.get());
     }
  
  public:
  
     virtual void OnMessage(MessageData* data)
     {
        if (data->message == "collision")
        {
  
           //Scene::CollisionData* cd = static_cast< Scene::CollisionData* >( data->userData );
  
           //Log::GetInstance().LogMessage( Log::LOG_INFO, __FUNCTION__,
           //                               "Collision detected between \%s and \%s at (\%f, \%f, \%f)",
           //                               dynamic_cast<Base*>(cd->mBodies[0])->GetName().c_str(),
           //                               dynamic_cast<Base*>(cd->mBodies[1])->GetName().c_str(),
           //                               cd->mLocation[0],
           //                               cd->mLocation[1],
           //                               cd->mLocation[2] );
           //
        }
     }
  private:
     dtCore::RefPtr<Scene> mScene;
  };
  
  class TestPhysicsApp : public Application
  {
  
  public:
  
     TestPhysicsApp(const std::string& configFile = "config.xml")
        : Application(configFile)
        , mLimit(50)
     {
        //setup some default physics values
        GetScene()->SetGravity(0.0f, 0.0f, -15.0f);
        GetScene()->GetPhysicsController()->GetWorldWrapper()->SetDamping(0.01f, 0.01f);
  
        RefPtr<Object> obj1 = new Object("Ground");
        RefPtr<Object> obj2 = new Object("FallingCrate");
        RefPtr<Object> obj3 = new Object("GroundCrate");
  
        obj1->LoadFile("models/terrain_simple.ive");
        obj2->LoadFile("models/physics_crate.ive");
        obj3->LoadFile("models/physics_crate.ive");
  
        //position the camera
        Transform position;
        position.Set(0.0f, -20.0f, 7.0f, 0.0f, 0.0f, 0.0f);
        GetCamera()->SetTransform(position);
  
        //position first falling crate
        position.Set(0.55f, 0.0f, 7.0f, 0.0f, 40.0f, 0.0f);
        obj2->SetTransform(position);
  
        //position the crate on the ground
        position.Set(0.0f, 0.0f, 4.f, 0.0f, 0.0f, 0.0f);
        obj3->SetTransform(position);
  
        double lx = 1.0;
        double ly = 1.0;
        double lz = 1.0;
  
        //create collision meshes
        obj1->SetCollisionMesh();
        obj2->SetCollisionBox();
        obj3->SetCollisionBox();
  
        //set the mass for objects
        dMass mass;
        dMassSetBox(&mass, 1.0, lx, ly, lz);
        obj2->SetMass(&mass);
        obj3->SetMass(&mass);
  
        //turn on the physics
        obj2->EnableDynamics();
        obj3->EnableDynamics();
  
        //Add the objects to the Scene to be rendered
        GetScene()->AddDrawable(obj1.get());
        GetScene()->AddDrawable(obj2.get());
        GetScene()->AddDrawable(obj3.get());
  
        //put the falling crate in the vector of dropped objects
        mObjects.push_back(obj2);
  
        updater = new Updater(GetScene());
  
        omm = new OrbitMotionModel(GetKeyboard(), GetMouse());
        omm->SetTarget(GetCamera());
  
        //calculate and set focal distance for orbit motion model (origin -> camera)
        Transform trans;
        GetCamera()->GetTransform(trans);
  
        osg::Vec3 camLoc;
        trans.GetTranslation(camLoc);
  
        osg::Vec3 origin(0.0f, 0.0f, 0.0f);
        omm->SetDistance((camLoc - origin).length());
  
        CreateHelpLabel();
     }
  
  protected:
  
     virtual ~TestPhysicsApp() {}
  
     virtual void PreFrame(const double deltaFrameTiime)
     {
        while (!mToAdd.empty())
        {
           GetScene()->AddDrawable(mToAdd.front().get());
           mObjects.push_back(mToAdd.front());
           mToAdd.pop();
        }
  
        while (!mToRemove.empty())
        {
           GetScene()->RemoveDrawable(mToRemove.front().get());
           mObjects.pop_front();
           mToRemove.pop();
        }
     }
  
     virtual bool KeyPressed(const dtCore::Keyboard* keyboard, int key)
     {
       // SetCollision____ must be called before setTransform so
       // that a dGeomID will exist before a prePhysicsUpdate, otherwise
       // the scale will never be applied to the physics geometry
        bool verdict(false);
        switch (key)
        {
           case 'p':
           {
              System::GetInstance().SetPause(!System::GetInstance().GetPause());
              verdict = true;
              break;
           }
           case osgGA::GUIEventAdapter::KEY_Escape:
           {
              while (!mToAdd.empty())
              {
                 mToAdd.pop();
              }
  
              while (!mToRemove.empty())
              {
                 mToRemove.pop();
              }
  
              while (!mObjects.empty())
              {
                 mObjects.pop_front();
              }
  
              Quit();
              verdict = true;
              break;
           }
           case 'b':
              {
                 if (mObjects.size() < mLimit)
                 {
                    RefPtr<Object> box = new Object("box");
                    box->LoadFile("models/physics_crate.ive");
  
                    float randomScale = RandFloat(0.5f, 2.0f);
                    box->SetScale(osg::Vec3(randomScale, randomScale, randomScale));
  
                    box->SetCollisionBox();
                    box->SetTransform(GetStartTransform());
                    //box->RenderCollisionGeometry();
  
                    double lx = 1.0;
                    double ly = 1.0;
                    double lz = 1.0;
  
                    dMass mass;
                    dMassSetBox(&mass, 1.0, lx, ly, lz);
                    box->SetMass(&mass);
  
                    box->EnableDynamics();
  
                    mToAdd.push(box);
                 }
                 else
                 {
                    mToRemove.push(mObjects.front());
                 }
                 verdict = true;
                 break;
           }
           case 's':
           {
              if (mObjects.size() < mLimit)
              {
                 RefPtr<Object> sphere = new Object("sphere");
                 sphere->LoadFile("models/physics_happy_sphere.ive");
  
                 float randomScale = RandFloat(0.5f, 2.0f);
                 sphere->SetScale(osg::Vec3(randomScale, randomScale, randomScale));
  
                 sphere->SetCollisionSphere();
                 sphere->SetTransform(GetStartTransform());
                 //sphere->RenderCollisionGeometry(true);
  
                 double radius = 0.5;
  
                 dMass mass;
                 dMassSetSphere(&mass, 1.0, radius);
                 sphere->SetMass(&mass);
                 sphere->EnableDynamics();
  
                 mToAdd.push(sphere);
              }
              else
              {
                 mToRemove.push(mObjects.front());
              }
              verdict = true;
              break;
           }
           case 'c':
           {
              if (mObjects.size() < mLimit)
              {
                 RefPtr<Object> cyl = new Object("cylinder");
                 cyl->LoadFile("models/physics_barrel.ive");
  
                 float randomScale = RandFloat(0.5f, 2.0f);
                 cyl->SetScale(osg::Vec3(randomScale, randomScale, randomScale));
  
                 cyl->SetCollisionCappedCylinder();
                 cyl->SetTransform(GetStartTransform());
                 //cyl->RenderCollisionGeometry(true);
  
                 double radius = 0.321;
                 double length = 1.0;
  
                 dMass mass;
                 dMassSetCappedCylinder(&mass, 1.0, 2, radius, length);
                 cyl->SetMass(&mass);
  
                 cyl->EnableDynamics();
  
                 mToAdd.push(cyl);
              }
              else
              {
                 mToRemove.push(mObjects.front());
              }
              verdict = true;
              break;
           }
           case osgGA::GUIEventAdapter::KEY_F1:
           {
              mLabel->SetActive(!mLabel->GetActive());
              break;
           }
           default:
           {
              break;
           }
        }
  
        return verdict;
     }
  
     //If a physical object is picked, apply a little spinning force to it
     virtual bool MouseButtonPressed(const dtCore::Mouse* mouse, dtCore::Mouse::MouseButton button)
     {
        if (button != 0) { return false; }
  
        dtCore::DeltaDrawable* drawable = GetView()->GetMousePickedObject();
        if (drawable == NULL) { return false; } //nothing picked
  
        dtCore::Physical* phys = dynamic_cast<dtCore::Physical*>(drawable);
        if (phys == NULL) { return false; } //didn't pick a Physical
  
        if (phys->DynamicsEnabled() == false) { return false; } //not enabled
  
        phys->GetBodyWrapper()->ApplyForce(osg::Vec3(0.f, 0.f, 120.f));
        phys->GetBodyWrapper()->ApplyTorque(osg::Vec3(0.f, 0.f, 60.f));
        return true;
     }
  
  
Use the mouse pick point to calculate the starting location Transform GetStartTransform() { osg::Vec3 xyz; if (GetView()->GetMousePickPosition(xyz)) { Transform xform; xyz[2] += 1.f; //bump up the z so objects aren't buried underground xform.SetTranslation(xyz); xform.SetRotation(RandFloat(0.0f, 180.0f), RandFloat(0.0f, 90.0f), RandFloat(0.0f, 90.0f));

           return xform;
        }
  
        return Transform();
     }
  
     private:
        void CreateHelpLabel()
        {
           mLabel = new dtABC::LabelActor();
           osg::Vec2 testSize(24.0f, 5.5f);
           mLabel->SetBackSize(testSize);
           mLabel->SetFontSize(0.8f);
           mLabel->SetTextAlignment(dtABC::LabelActor::AlignmentEnum::LEFT_CENTER);
           mLabel->SetText(CreateHelpLabelText());
           mLabel->SetEnableDepthTesting(false);
           mLabel->SetEnableLighting(false);
  
           GetCamera()->AddChild(mLabel.get());
           dtCore::Transform labelOffset(-17.0f, 50.0f, 10.5f, 0.0f, 90.0f, 0.0f);
           mLabel->SetTransform(labelOffset, dtCore::Transformable::REL_CS);
           AddDrawable(GetCamera());
        }
  
        std::string CreateHelpLabelText()
        {
           std::string testString("");
           testString += "F1: Toggle Help Screen\n";
           testString += "\n";
           testString += "b: Add box at mouse position\n";
           testString += "c: Add cylinder at mouse position\n";
           testString += "s: Add sphere at mouse position\n";
           testString += "p: Pause System\n";
  
           return testString;
        }
  
     const unsigned int mLimit;
  
     std::queue< RefPtr<Object> > mToAdd;
     std::queue< RefPtr<Object> > mToRemove;
     std::deque< RefPtr<Object> > mObjects;
  
     RefPtr<Updater> updater;
     RefPtr<OrbitMotionModel> omm;
     dtCore::RefPtr<dtABC::LabelActor> mLabel;
  };
  
  int main(int argc, char** argv)
  {
     dtCore::SetDataFilePathList( dtCore::GetDeltaRootPath() + "/examples/data" + ";");
  
     RefPtr<TestPhysicsApp> app = new TestPhysicsApp("config.xml");
  
     app->Config();
     app->Run();
  
     return 0;
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.