示例#1
0
void World6::rotate_planets()
   {
   m_dayPeriodSun = new CLerpNodePathInterval("dayPeriodSunInterval",
                                              20,
                                              CLerpInterval::BT_no_blend,
                                              true,
                                              false,
                                              m_sun,
                                              NodePath());
   m_dayPeriodSun->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodSun->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMercury =
      new CLerpNodePathInterval("orbitPeriodMercuryInterval",
                                0.241 * m_yearscale,
                                CLerpInterval::BT_no_blend,
                                true,
                                false,
                                m_orbitRootMercury,
                                NodePath());
   m_orbitPeriodMercury->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMercury->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMercury = new CLerpNodePathInterval("dayPeriodMercuryInterval",
                                                  59 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_mercury,
                                                  NodePath());
   m_dayPeriodMercury->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMercury->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodVenus = new CLerpNodePathInterval("orbitPeriodVenusInterval",
                                                  0.615 * m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootVenus,
                                                  NodePath());
   m_orbitPeriodVenus->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodVenus->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodVenus = new CLerpNodePathInterval("dayPeriodVenusInterval",
                                                  243 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_venus,
                                                  NodePath());
   m_dayPeriodVenus->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodVenus->set_end_hpr  (LVecBase3f(360, 0, 0));

   // Here the earth interval has been changed to rotate like the rest of the
   // planets and send a message before it starts turning again. To send a
   // message, the call is simply messenger.send("message"). The "newYear"
   // message is picked up by the accept("newYear"...) statement earlier, and
   // calls the incYear function as a result
   m_orbitPeriodEarth = new CLerpNodePathInterval("orbitPeriodEarthInterval",
                                                  m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootEarth,
                                                  NodePath());
   m_orbitPeriodEarth->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodEarth->set_end_hpr  (LVecBase3f(360, 0, 0));
   m_orbitPeriodEarth->set_done_event("newYear");

   m_dayPeriodEarth = new CLerpNodePathInterval("dayPeriodEarthInterval",
                                                  m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_earth,
                                                  NodePath());
   m_dayPeriodEarth->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodEarth->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMoon = new CLerpNodePathInterval("orbitPeriodMoonInterval",
                                                  0.0749 * m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootMoon,
                                                  NodePath());
   m_orbitPeriodMoon->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMoon->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMoon = new CLerpNodePathInterval("dayPeriodMoonInterval",
                                                  0.0749 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_moon,
                                                  NodePath());
   m_dayPeriodMoon->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMoon->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMars = new CLerpNodePathInterval("orbitPeriodMarsInterval",
                                                 1.881 * m_yearscale,
                                                 CLerpInterval::BT_no_blend,
                                                 true,
                                                 false,
                                                 m_orbitRootMars,
                                                 NodePath());
   m_orbitPeriodMars->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMars->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMars = new CLerpNodePathInterval("dayPeriodMarsInterval",
                                               1.03 * m_dayscale,
                                               CLerpInterval::BT_no_blend,
                                               true,
                                               false,
                                               m_mars,
                                               NodePath());
   m_dayPeriodMars->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMars->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodSun->loop();
   m_orbitPeriodMercury->loop();
   m_dayPeriodMercury->loop();
   m_orbitPeriodVenus->loop();
   m_dayPeriodVenus->loop();
   m_orbitPeriodEarth->loop();
   m_dayPeriodEarth->loop();
   m_orbitPeriodMoon->loop();
   m_dayPeriodMoon->loop();
   m_orbitPeriodMars->loop();
   m_dayPeriodMars->loop();

   // Note: setup a task to step the interval manager
   AsyncTaskManager::get_global_ptr()->add(
      new GenericAsyncTask("intervalManagerTask", step_interval_manager, this));
   }
示例#2
0
World::World(WindowFramework* windowFrameworkPtr)
   : m_windowFrameworkPtr(windowFrameworkPtr)
   {
   // preconditions
   if(m_windowFrameworkPtr == NULL)
      {
      nout << "ERROR: World::World(WindowFramework* windowFrameworkPtr) parameter windowFrameworkPtr cannot be NULL." << endl;
      return;
      }

   m_keyMap.resize(K_keys);
   m_keyMap[K_left     ] = false;
   m_keyMap[K_right    ] = false;
   m_keyMap[K_forward  ] = false;
   m_keyMap[K_cam_left ] = false;
   m_keyMap[K_cam_right] = false;
   m_windowFrameworkPtr->set_background_type(WindowFramework::BT_black);

   // Post the instructions

   m_titleNp = add_title("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)");
   m_inst1Np = add_instructions(0.95, "[ESC]: Quit");
   m_inst2Np = add_instructions(0.90, "[Left Arrow]: Rotate Ralph Left");
   m_inst3Np = add_instructions(0.85, "[Right Arrow]: Rotate Ralph Right");
   m_inst4Np = add_instructions(0.80, "[Up Arrow]: Run Ralph Forward");
   m_inst6Np = add_instructions(0.70, "[A]: Rotate Camera Left");
   m_inst7Np = add_instructions(0.65, "[S]: Rotate Camera Right");

   // Set up the environment
   //
   // This environment model contains collision meshes.  If you look
   // in the egg file, you will see the following:
   //
   //    <Collide> { Polyset keep descend }
   //
   // This tag causes the following mesh to be converted to a collision
   // mesh -- a mesh which is optimized for collision, not rendering.
   // It also keeps the original mesh, so there are now two copies ---
   // one optimized for rendering, one for collisions.

   NodePath modelsNp = m_windowFrameworkPtr->get_panda_framework()->get_models();
   m_environNp = m_windowFrameworkPtr->load_model(modelsNp, "../models/world");
   NodePath renderNp = m_windowFrameworkPtr->get_render();
   m_environNp.reparent_to(renderNp);
   m_environNp.set_pos(0,0,0);

   // Create the main character, Ralph
   LPoint3f ralphStartPos = m_environNp.find("**/start_point").get_pos();
   CActor::AnimMap ralphAnims;
   ralphAnims["../models/ralph-run"].push_back("run");
   ralphAnims["../models/ralph-walk"].push_back("walk");
   m_ralph.load_actor(m_windowFrameworkPtr,
                      "../models/ralph",
                      &ralphAnims,
                      PartGroup::HMF_ok_wrong_root_name|
                      PartGroup::HMF_ok_anim_extra|
                      PartGroup::HMF_ok_part_extra);
   m_ralph.reparent_to(renderNp);
   m_ralph.set_scale(0.2);
   m_ralph.set_pos(ralphStartPos);

   // Create a floater object.  We use the "floater" as a temporary
   // variable in a variety of calculations.

   m_floaterNp = NodePath("floater");
   m_floaterNp.reparent_to(renderNp);

   // Accept the control keys for movement and rotation
   m_windowFrameworkPtr->enable_keyboard();
   m_windowFrameworkPtr->get_panda_framework()->define_key("escape"        , "sysExit"    , sys_exit                        , NULL);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_left"    , "left"       , call_set_key<K_left     , true >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_right"   , "right"      , call_set_key<K_right    , true >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_up"      , "forward"    , call_set_key<K_forward  , true >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("a"             , "cam-left"   , call_set_key<K_cam_left , true >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("s"             , "cam-right"  , call_set_key<K_cam_right, true >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_left-up" , "leftUp"     , call_set_key<K_left     , false>, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_right-up", "rightUp"    , call_set_key<K_right    , false>, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("arrow_up-up"   , "forwardUp"  , call_set_key<K_forward  , false>, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("a-up"          , "cam-leftUp" , call_set_key<K_cam_left , false>, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("s-up"          , "cam-rightUp", call_set_key<K_cam_right, false>, this);

   PT(GenericAsyncTask) taskPtr = new GenericAsyncTask("moveTask", call_move, this);
   if(taskPtr != NULL)
      {
      AsyncTaskManager::get_global_ptr()->add(taskPtr);
      }

   // Game state variables
   m_isMoving = false;

   // Set up the camera

   // Note: no need to disable the mouse in C++
   NodePath cameraNp = m_windowFrameworkPtr->get_camera_group();
   cameraNp.set_pos(m_ralph.get_x(), m_ralph.get_y()+10, 2);

   // We will detect the height of the terrain by creating a collision
   // ray and casting it downward toward the terrain.  One ray will
   // start above ralph's head, and the other will start above the camera.
   // A ray may hit the terrain, or it may hit a rock or a tree.  If it
   // hits the terrain, we can detect the height.  If it hits anything
   // else, we rule that the move is illegal.

   NodePath ralphGroundColNp;
   m_ralphGroundRayPtr = new CollisionRay();
   if(m_ralphGroundRayPtr != NULL)
      {
      m_ralphGroundRayPtr->set_origin(0, 0, 1000);
      m_ralphGroundRayPtr->set_direction(0, 0, -1);
      m_ralphGroundColPtr = new CollisionNode("ralphRay");
      if(m_ralphGroundColPtr != NULL)
         {
         m_ralphGroundColPtr->add_solid(m_ralphGroundRayPtr);
         m_ralphGroundColPtr->set_from_collide_mask(BitMask32::bit(0));
         m_ralphGroundColPtr->set_into_collide_mask(BitMask32::all_off());
         ralphGroundColNp = m_ralph.attach_new_node(m_ralphGroundColPtr);
         m_ralphGroundHandlerPtr = new CollisionHandlerQueue();
         if(m_ralphGroundHandlerPtr != NULL)
            {
            m_collisionTraverser.add_collider(ralphGroundColNp, m_ralphGroundHandlerPtr);
            }
         }
      }

   NodePath camGroundColNp;
   m_camGroundRayPtr = new CollisionRay();
   if(m_camGroundRayPtr != NULL)
      {
      m_camGroundRayPtr->set_origin(0, 0, 1000);
      m_camGroundRayPtr->set_direction(0, 0, -1);
      m_camGroundColPtr = new CollisionNode("camRay");
      if(m_camGroundColPtr != NULL)
         {
         m_camGroundColPtr->add_solid(m_camGroundRayPtr);
         m_camGroundColPtr->set_from_collide_mask(BitMask32::bit(0));
         m_camGroundColPtr->set_into_collide_mask(BitMask32::all_off());
         camGroundColNp = cameraNp.attach_new_node(m_camGroundColPtr);
         m_camGroundHandlerPtr = new CollisionHandlerQueue();
         if(m_camGroundHandlerPtr != NULL)
            {
            m_collisionTraverser.add_collider(camGroundColNp, m_camGroundHandlerPtr);
            }
         }
      }

   // Uncomment this line to see the collision rays
   //ralphGroundColNp.show();
   //camGroundColNp.show();

   // Uncomment this line to show a visual representation of the
   // collisions occuring
   //m_collisionTraverser.show_collisions(renderNp);

   // Create some lighting
   PT(AmbientLight) ambientLightPtr = new AmbientLight("ambientLight");
   if(ambientLightPtr != NULL)
      {
      ambientLightPtr->set_color(Colorf(.3, .3, .3, 1));
      renderNp.set_light(renderNp.attach_new_node(ambientLightPtr));
      }
   PT(DirectionalLight) directionalLightPtr = new DirectionalLight("directionalLightPtr");
   if(directionalLightPtr != NULL)
      {
      directionalLightPtr->set_direction(LVecBase3f(-5, -5, -5));
      directionalLightPtr->set_color(Colorf(1, 1, 1, 1));
      directionalLightPtr->set_specular_color(Colorf(1, 1, 1, 1));
      renderNp.set_light(renderNp.attach_new_node(directionalLightPtr));
      }
   }
示例#3
0
World::World(WindowFramework* windowFramework)
    : m_windowFramework(windowFramework),
      m_title(),
      m_inst1(),
      m_inst2(),
      m_inst3(),
      m_inst4(),
      m_altCam(),
      m_teapot(),
      m_teapotInterval(),
      m_bufferViewer(NULL)
      // m_tvMen
{
    // Note: set background color here
    m_windowFramework->get_graphics_output()->get_active_display_region(0)->
    set_clear_color(Colorf(0, 0, 0, 1));

    // Post the instructions.
    m_title = add_title("Panda3D: Tutorial - Using Render-to-Texture");
    m_inst1 = add_instructions(0.95,"ESC: Quit");
    m_inst2 = add_instructions(0.90,"Up/Down: Zoom in/out on the Teapot");
    m_inst3 = add_instructions(0.85,"Left/Right: Move teapot left/right");
    m_inst4 = add_instructions(0.80,"V: View the render-to-texture results");

    //we get a handle to the default window
    PT(GraphicsOutput) mainWindow = m_windowFramework->get_graphics_output();

    // we now get buffer thats going to hold the texture of our new scene
    PT(GraphicsOutput) altBuffer = mainWindow->make_texture_buffer(
                                       "hello", 256, 256);

    // now we have to setup a new scene graph to make this scene
    NodePath altRender("new render");

    // this takes care of setting up the camera properly
    m_altCam = m_windowFramework->make_camera();
    // Note: set the size and shape of the "film" within the lens equal to the
    //       buffer of our new scene
    DCAST(Camera, m_altCam.node())->get_lens()->set_film_size(
        altBuffer->get_x_size(), altBuffer->get_y_size());
    // Note: make a DisplayRegion for the camera
    PT(DisplayRegion) dr = altBuffer->make_display_region(0, 1, 0, 1);
    dr->set_sort(0);
    dr->set_camera(m_altCam);
    m_altCam.reparent_to(altRender);
    m_altCam.set_pos(0, -10, 0);

    // get the teapot and rotates it for a simple animation
    const NodePath& models =
        m_windowFramework->get_panda_framework()->get_models();
    m_teapot = m_windowFramework->load_model(models, "../models/teapot");
    m_teapot.reparent_to(altRender);
    m_teapot.set_pos(0, 0, -1);

    const bool bakeInStart = true;
    const bool fluid = false;
    m_teapotInterval = new CLerpNodePathInterval("teapotInterval", 1.5,
            CLerpInterval::BT_no_blend, bakeInStart, fluid, m_teapot, NodePath());
    m_teapotInterval->set_start_hpr(m_teapot.get_hpr());
    m_teapotInterval->set_end_hpr(LVecBase3f(m_teapot.get_h()+360,
                                  m_teapot.get_p()+360,
                                  m_teapot.get_r()+360));
    m_teapotInterval->loop();

    // put some lighting on the teapot
    PT(DirectionalLight) dlight = new DirectionalLight("dlight");
    PT(AmbientLight) alight = new AmbientLight("alight");
    NodePath dlnp = altRender.attach_new_node(dlight);
    NodePath alnp = altRender.attach_new_node(alight);
    dlight->set_color(Colorf(0.8, 0.8, 0.5, 1));
    alight->set_color(Colorf(0.2, 0.2, 0.2, 1));
    dlnp.set_hpr(0, -60, 0);
    altRender.set_light(dlnp);
    altRender.set_light(alnp);

    // Panda contains a built-in viewer that lets you view the results of
    // your render-to-texture operations.  This code configures the viewer.

    WORLD_DEFINE_KEY("v", "toggleBufferViewer", toggle_buffer_viewer);
    m_bufferViewer = new CBufferViewer(m_windowFramework);
    m_bufferViewer->set_position(CBufferViewer::CP_llcorner);
    m_bufferViewer->set_card_size(1.0, 0.0);

    // Create the tv-men. Each TV-man will display the
    // offscreen-texture on his TV screen.
    make_tv_man(-5, 30,  1, altBuffer->get_texture(), 0.9);
    make_tv_man( 5, 30,  1, altBuffer->get_texture(), 1.4);
    make_tv_man( 0, 23, -3, altBuffer->get_texture(), 2.0);
    make_tv_man(-5, 20, -6, altBuffer->get_texture(), 1.1);
    make_tv_man( 5, 18, -5, altBuffer->get_texture(), 1.7);

    WORLD_DEFINE_KEY("escape", "exit", quit);
    WORLD_DEFINE_KEY("arrow_up", "zoomIn", zoom_in);
    WORLD_DEFINE_KEY("arrow_down", "zoomOut", zoom_out);
    WORLD_DEFINE_KEY("arrow_left", "moveLeft", move_left);
    WORLD_DEFINE_KEY("arrow_right", "moveRight", move_right);

    WORLD_ADD_TASK("worldAsyncTask", async_task);
}
示例#4
0
World::World(WindowFramework* windowFrameworkPtr)
   : m_windowFrameworkPtr(windowFrameworkPtr)
   {
   // preconditions
   if(m_windowFrameworkPtr == NULL)
      {
      nout << "ERROR: parameter windowFrameworkPtr cannot be NULL." << endl;
      return;
      }

   // This code puts the standard title and instruction text on screen
   COnscreenText title("title", COnscreenText::TS_plain);
   title.set_text("Panda3D: Tutorial - Joint Manipulation");
   title.set_fg(Colorf(1,1,1,1));
   title.set_pos(LVecBase2f(0.7, -0.95));
   title.set_scale(0.07);
   title.reparent_to(m_windowFrameworkPtr->get_aspect_2d());
   m_titleNp = title.generate();
   m_esckeyTextNp   = gen_label_text("ESC: Quit"      , 0);
   m_onekeyTextNp   = gen_label_text("[1]: Teapot"    , 1);
   m_twokeyTextNp   = gen_label_text("[2]: Candy cane", 2);
   m_threekeyTextNp = gen_label_text("[3]: Banana"    , 3);
   m_fourkeyTextNp  = gen_label_text("[4]: Sword"     , 4);

   // setup key input
   m_windowFrameworkPtr->enable_keyboard();
   m_windowFrameworkPtr->get_panda_framework()->define_key("escape", "Exit"     , sys_exit      , NULL);
   m_windowFrameworkPtr->get_panda_framework()->define_key("1"     , "Teapot"   , call_set_object<M_teapot    >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("2"     , "CandyCane", call_set_object<M_candy_cane>, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("3"     , "Banana"   , call_set_object<M_banana    >, this);
   m_windowFrameworkPtr->get_panda_framework()->define_key("4"     , "Sword"    , call_set_object<M_sword     >, this);

   // Disable mouse-based camera-control
   // Note: disable by default in C++

   // Position the camera
   m_windowFrameworkPtr->get_camera_group().set_pos(0,-15, 2);

   // Load our animated character
   // Note: File eve_walk.egg is broken!
   //       The name of the animation is case sensitive and at line 13 of file
   //       eve_walk.egg you should read `Eve' instead of `eve'. You need to
   //       correct this in order to bind the animation automatically using
   //       auto_bind() or WindowFramework::loop_animations(). Or you can use
   //       PartGroup::HMF_ok_wrong_root_name to ask auto_bind() to be more
   //       forgiving.
   CActor::AnimMap eveAnims;
   eveAnims["../models/eve_walk"].push_back("walk");
   m_eve.load_actor(m_windowFrameworkPtr,
                    "../models/eve",
                    &eveAnims,
                    PartGroup::HMF_ok_wrong_root_name);

   // Put it in the scene
   NodePath renderNp = m_windowFrameworkPtr->get_render();
   m_eve.reparent_to(renderNp);

   // Now we use control_joint to get a NodePath that's in control of her neck
   // This must be done before any animations are played
   m_eveNeckNp = m_eve.control_joint("Neck");

   // We now play an animation. An animation must be played, or at least posed
   // for the nodepath we just got from control_joint to actually effect the model
   m_eve.find_anim("walk")->set_play_rate(2);
   m_eve.loop("walk", true);

   // Now we add a task that will take care of turning the head
   PT(GenericAsyncTask) turnHeadTask = new GenericAsyncTask("turnHead", call_turn_head, this);
   if(turnHeadTask != NULL)
      {
      AsyncTaskManager::get_global_ptr()->add(turnHeadTask);
      }

   // Now we will expose the joint the hand joint. ExposeJoint allows us to
   // get the position of a joint while it is animating. This is different than
   // control_joint which stops that joint from animating but lets us move it.
   // This is particularly useful for putting an object (like a weapon) in an
   // actor's hand
   m_eveRightHandNp = m_eve.expose_joint("RightHand");

   // This is a table with models, positions, rotations, and scales of objects to
   // be attached to our exposed joint. These are stock models and so they needed
   // to be repositioned to look right.
   vector<ModelData> positions(M_models);
   positions[M_teapot    ] = ModelData("../models/teapot"   , LVecBase3f(0.00,-0.66,-0.95), LVecBase3f(90,  0,90), 0.40);
   positions[M_candy_cane] = ModelData("../models/candycane", LVecBase3f(0.15,-0.99,-0.22), LVecBase3f(90,  0,90), 1.00);
   positions[M_banana    ] = ModelData("../models/banana"   , LVecBase3f(0.08,-0.10, 0.09), LVecBase3f( 0,-90, 0), 1.75);
   positions[M_sword     ] = ModelData("../models/sword"    , LVecBase3f(0.11, 0.19, 0.06), LVecBase3f( 0,  0,90), 1.00);
   // A list that will store our models objects
   m_modelsNp.reserve(M_models);
   NodePath modelsNp = m_windowFrameworkPtr->get_panda_framework()->get_models();
   for(vector<ModelData>::iterator i = positions.begin(); i < positions.end(); ++i)
      {
      // Load the model
      NodePath np = m_windowFrameworkPtr->load_model(modelsNp, i->m_filename);
      // Position it
      np.set_pos(i->m_pos);
      // Rotate it
      np.set_hpr(i->m_hpr);
      // Scale it
      np.set_scale(i->m_scale);
      // Reparent the model to the exposed joint. That way when the joint moves,
      // the model we just loaded will move with it.
      np.reparent_to(m_eveRightHandNp);
      // Add it to our models list
      m_modelsNp.push_back(np);
      }

   // Make object 0 the first shown
   set_object(M_teapot);
   // Put in some default lighting
   setup_lights();
   }
示例#5
0
World::World(WindowFramework* windowFrameworkPtr)
   : UP(0,0,1),
     m_windowFrameworkPtr(windowFrameworkPtr)
   {
   // preconditions
   if(m_windowFrameworkPtr == NULL)
      {
      nout << "ERROR: parameter windowFrameworkPtr cannot be NULL." << endl;
      return;
      }

   // This code puts the standard title and instruction text on screen
   COnscreenText title("title", COnscreenText::TS_plain);
   title.set_text("Panda3D: Tutorial - Collision Detection");
   title.set_fg(Colorf(1,1,1,1));
   title.set_pos(LVecBase2f(0.7,-0.95));
   title.set_scale(0.07);
   title.reparent_to(m_windowFrameworkPtr->get_aspect_2d());
   m_titleNp = title.generate();


   COnscreenText instructions("instructions");
   instructions.set_text("Mouse pointer tilts the board");
   instructions.set_pos(LVecBase2f(-1.3, 0.95));
   instructions.set_fg(Colorf(1,1,1,1));
   instructions.set_align(TextNode::A_left);
   instructions.set_scale(0.05);
   instructions.reparent_to(m_windowFrameworkPtr->get_aspect_2d());
   m_instructionsNp = instructions.generate();

   // Escape quits
   m_windowFrameworkPtr->enable_keyboard();
   m_windowFrameworkPtr->get_panda_framework()->define_key("escape", "sysExit", sys_exit, NULL);

   // Disable mouse-based camera control
   // Note: irrelevant in C++

   // Place the camera
   NodePath cameraNp = m_windowFrameworkPtr->get_camera_group();
   cameraNp.set_pos_hpr(0, 0, 25, 0, -90, 0);

   // Load the maze and place it in the scene
   NodePath modelsNp = m_windowFrameworkPtr->get_panda_framework()->get_models();
   m_mazeNp = m_windowFrameworkPtr->load_model(modelsNp, "../models/maze");
   NodePath renderNp = m_windowFrameworkPtr->get_render();
   m_mazeNp.reparent_to(renderNp);

   // Most times, you want collisions to be tested against invisible geometry
   // rather than every polygon. This is because testing against every polygon
   // in the scene is usually too slow. You can have simplified or approximate
   // geometry for the solids and still get good results.
   //
   // Sometimes you'll want to create and position your own collision solids in
   // code, but it's often easier to have them built automatically. This can be
   // done by adding special tags into an egg file. Check maze.egg and ball.egg
   // and look for lines starting with <Collide>. The part is brackets tells
   // Panda exactly what to do. Polyset means to use the polygons in that group
   // as solids, while Sphere tells panda to make a collision sphere around them
   // Keep means to keep the polygons in the group as visable geometry (good
   // for the ball, not for the triggers), and descend means to make sure that
   // the settings are applied to any subgroups.
   //
   // Once we have the collision tags in the models, we can get to them using
   // NodePath's find command

   // Find the collision node named wall_collide
   m_wallsNp = m_mazeNp.find("**/wall_collide");

   // Collision objects are sorted using BitMasks. BitMasks are ordinary numbers
   // with extra methods for working with them as binary bits. Every collision
   // solid has both a from mask and an into mask. Before Panda tests two
   // objects, it checks to make sure that the from and into collision masks
   // have at least one bit in common. That way things that shouldn't interact
   // won't. Normal model nodes have collision masks as well. By default they
   // are set to bit 20. If you want to collide against actual visable polygons,
   // set a from collide mask to include bit 20
   //
   // For this example, we will make everything we want the ball to collide with
   // include bit 0
   m_wallsNp.node()->set_into_collide_mask(BitMask32::bit(0));
   // CollisionNodes are usually invisible but can be shown. Uncomment the next
   // line to see the collision walls
   // m_wallsNp.show();

   // We will now find the triggers for the holes and set their masks to 0 as
   // well. We also set their names to make them easier to identify during
   // collisions
   m_loseTriggers.reserve(NB_HOLES);
   for(int i = 0; i < NB_HOLES; ++i)
      {
      ostringstream filename;
      filename << "**/hole_collide" << i;
      NodePath triggerNp = m_mazeNp.find(filename.str());
      triggerNp.node()->set_into_collide_mask(BitMask32::bit(0));
      triggerNp.node()->set_name("loseTrigger");
      m_loseTriggers.push_back(triggerNp);
      // Uncomment this line to see the triggers
      // triggerNp.show();
      }

   // Ground_collide is a single polygon on the same plane as the ground in the
   // maze. We will use a ray to collide with it so that we will know exactly
   // what height to put the ball at every frame. Since this is not something
   // that we want the ball itself to collide with, it has a different
   // bitmask.
   m_mazeGroundNp = m_mazeNp.find("**/ground_collide");
   m_mazeGroundNp.node()->set_into_collide_mask(BitMask32::bit(1));

   // Load the ball and attach it to the scene
   // It is on a root dummy node so that we can rotate the ball itself without
   // rotating the ray that will be attached to it
   m_ballRootNp = renderNp.attach_new_node("ballRoot");
   m_ballNp = m_windowFrameworkPtr->load_model(modelsNp, "../models/ball");
   m_ballNp.reparent_to(m_ballRootNp);

   // Find the collision sphere for the ball which was created in the egg file
   // Notice that it has a from collision mask of bit 0, and an into collision
   // mask of no bits. This means that the ball can only cause collisions, not
   // be collided into
   m_ballSphereNp = m_ballNp.find("**/ball");
   DCAST(CollisionNode, m_ballSphereNp.node())->set_from_collide_mask(BitMask32::bit(0));
   m_ballSphereNp.node()->set_into_collide_mask(BitMask32::all_off());

   // No we create a ray to start above the ball and cast down. This is to
   // Determine the height the ball should be at and the angle the floor is
   // tilting. We could have used the sphere around the ball itself, but it
   // would not be as reliable

   // Create the ray
   m_ballGroundRayPtr = new CollisionRay();
   if(m_ballGroundRayPtr != NULL)
      {
      // Set its origin
      m_ballGroundRayPtr->set_origin(0,0,10);
      // And its direction
      m_ballGroundRayPtr->set_direction(0,0,-1);
      // Collision solids go in CollisionNode
      // Create and name the node
      m_ballGroundColPtr = new CollisionNode("groundRay");
      if(m_ballGroundColPtr != NULL)
         {
         // Add the ray
         m_ballGroundColPtr->add_solid(m_ballGroundRayPtr);
         // Set its bitmasks
         m_ballGroundColPtr->set_from_collide_mask(BitMask32::bit(1));
         m_ballGroundColPtr->set_into_collide_mask(BitMask32::all_off());
         // Attach the node to the ballRoot so that the ray is relative to the ball
         // (it will always be 10 feet over the ball and point down)
         m_ballGroundColNp = m_ballRootNp.attach_new_node(m_ballGroundColPtr);
         // Uncomment this line to see the ray
         // m_ballGroundColNp.show();
         }
      }

   // Finally, we create a CollisionTraverser. CollisionTraversers are what
   // do the job of calculating collisions
   // Note: no need to in this implementation

   // Collision traversers tell collision handlers about collisions, and then
   // the handler decides what to do with the information. We are using a
   // CollisionHandlerQueue, which simply creates a list of all of the
   // collisions in a given pass. There are more sophisticated handlers like
   // one that sends events and another that tries to keep collided objects
   // apart, but the results are often better with a simple queue
   m_cHandlerPtr = new CollisionHandlerQueue();
   if(m_cHandlerPtr != NULL)
      {
      // Now we add the collision nodes that can create a collision to the
      // traverser. The traverser will compare these to all others nodes in the
      // scene. There is a limit of 32 CollisionNodes per traverser
      // We add the collider, and the handler to use as a pair
      m_cTrav.add_collider(m_ballSphereNp, m_cHandlerPtr);
      m_cTrav.add_collider(m_ballGroundColNp, m_cHandlerPtr);
      }

   // Collision traversers have a built in tool to help visualize collisions.
   // Uncomment the next line to see it.
   // m_cTrav.show_collisions(renderNp);

   // This section deals with lighting for the ball. Only the ball was lit
   // because the maze has static lighting pregenerated by the modeler
   PT(AmbientLight) ambientLightPtr = new AmbientLight("ambientLight");
   if(ambientLightPtr != NULL)
      {
      ambientLightPtr->set_color(Colorf(0.55, 0.55, 0.55, 1));
      m_ballRootNp.set_light(renderNp.attach_new_node(ambientLightPtr));
      }
   PT(DirectionalLight) directionalLightPtr = new DirectionalLight("directionalLight");
   if(directionalLightPtr != NULL)
      {
      directionalLightPtr->set_direction(LVecBase3f(0, 0, -1));
      directionalLightPtr->set_color(Colorf(0.375, 0.375, 0.375, 1));
      directionalLightPtr->set_specular_color(Colorf(1, 1, 1, 1));
      m_ballRootNp.set_light(renderNp.attach_new_node(directionalLightPtr));
      }

   // This section deals with adding a specular highlight to the ball to make
   // it look shiny
   PT(Material) materialPtr = new Material();
   if(materialPtr != NULL)
      {
      materialPtr->set_specular(Colorf(1,1,1,1));
      materialPtr->set_shininess(96);
      m_ballNp.set_material(materialPtr, 1);
      }

   // Finally, we call start for more initialization
   start();
   }
示例#6
0
void World5::rotate_planets()
   {
   // rotatePlanets creates intervals to actually use the hierarchy we created
   // to turn the sun, planets, and moon to give a rough representation of the
   // solar system. The next lesson will go into more depth on intervals.
   m_dayPeriodSun = new CLerpNodePathInterval("dayPeriodSunInterval",
                                              20,
                                              CLerpInterval::BT_no_blend,
                                              true,
                                              false,
                                              m_sun,
                                              NodePath());
   m_dayPeriodSun->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodSun->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMercury =
      new CLerpNodePathInterval("orbitPeriodMercuryInterval",
                                0.241 * m_yearscale,
                                CLerpInterval::BT_no_blend,
                                true,
                                false,
                                m_orbitRootMercury,
                                NodePath());
   m_orbitPeriodMercury->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMercury->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMercury = new CLerpNodePathInterval("dayPeriodMercuryInterval",
                                                  59 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_mercury,
                                                  NodePath());
   m_dayPeriodMercury->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMercury->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodVenus = new CLerpNodePathInterval("orbitPeriodVenusInterval",
                                                  0.615 * m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootVenus,
                                                  NodePath());
   m_orbitPeriodVenus->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodVenus->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodVenus = new CLerpNodePathInterval("dayPeriodVenusInterval",
                                                  243 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_venus,
                                                  NodePath());
   m_dayPeriodVenus->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodVenus->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodEarth = new CLerpNodePathInterval("orbitPeriodEarthInterval",
                                                  m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootEarth,
                                                  NodePath());
   m_orbitPeriodEarth->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodEarth->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodEarth = new CLerpNodePathInterval("dayPeriodEarthInterval",
                                                  m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_earth,
                                                  NodePath());
   m_dayPeriodEarth->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodEarth->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMoon = new CLerpNodePathInterval("orbitPeriodMoonInterval",
                                                  0.0749 * m_yearscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_orbitRootMoon,
                                                  NodePath());
   m_orbitPeriodMoon->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMoon->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMoon = new CLerpNodePathInterval("dayPeriodMoonInterval",
                                                  0.0749 * m_dayscale,
                                                  CLerpInterval::BT_no_blend,
                                                  true,
                                                  false,
                                                  m_moon,
                                                  NodePath());
   m_dayPeriodMoon->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMoon->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_orbitPeriodMars = new CLerpNodePathInterval("orbitPeriodMarsInterval",
                                                 1.881 * m_yearscale,
                                                 CLerpInterval::BT_no_blend,
                                                 true,
                                                 false,
                                                 m_orbitRootMars,
                                                 NodePath());
   m_orbitPeriodMars->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_orbitPeriodMars->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodMars = new CLerpNodePathInterval("dayPeriodMarsInterval",
                                               1.03 * m_dayscale,
                                               CLerpInterval::BT_no_blend,
                                               true,
                                               false,
                                               m_mars,
                                               NodePath());
   m_dayPeriodMars->set_start_hpr(LVecBase3f(  0, 0, 0));
   m_dayPeriodMars->set_end_hpr  (LVecBase3f(360, 0, 0));

   m_dayPeriodSun->loop();
   m_orbitPeriodMercury->loop();
   m_dayPeriodMercury->output(nout);
   m_dayPeriodMercury->loop();
   m_orbitPeriodVenus->loop();
   m_dayPeriodVenus->loop();
   m_orbitPeriodEarth->loop();
   m_dayPeriodEarth->loop();
   m_orbitPeriodMoon->loop();
   m_dayPeriodMoon->loop();
   m_orbitPeriodMars->loop();
   m_dayPeriodMars->loop();

   // Note: setup a task to step the interval manager
   AsyncTaskManager::get_global_ptr()->add(
      new GenericAsyncTask("intervalManagerTask", step_interval_manager, this));
   }