Python to C++

I am new to Panda3D, properly I learn Visual studio C++ programming language… and never learn python before. But for panda3D, mostly there are programming by python programming language. Then I am here to get some help from u all to help translate code example below into C++… then i can more know about collision detection from panda 3D…
These code is the tutorial from panda3d software… So I hopefully can giv me some example of coding about collision detection:

class World(DirectObject):
  def __init__(self):
	self.title = OnscreenText(text="Panda3D: Tutorial - Collision Detection",
                              style=1, fg=(1,1,1,1),
                              pos=(0.7,-0.95), scale = .07)
    	self.instructions = OnscreenText(text="Mouse pointer tilts the board",
                                     pos = (-1.3, .95), fg=(1,1,1,1),
                                     align = TextNode.ALeft, scale = .05)
	self.accept("escape", sys.exit)        # Escape quits
    	base.disableMouse()                    # Disable mouse-based camera control
    	camera.setPosHpr(0, 0, 25, 0, -90, 0)  # Place the camera

    	# Load the maze and place it in the scene
    	self.maze = loader.loadModel("models/maze")
    	self.maze.reparentTo(render)
self.walls = self.maze.find("**/wall_collide")
self.walls.node().setIntoCollideMask(BitMask32.bit(0))
self.loseTriggers = []
    for i in range(6):
      trigger = self.maze.find("**/hole_collide" + str(i))
      trigger.node().setIntoCollideMask(BitMask32.bit(0))
      trigger.node().setName("loseTrigger")
      self.loseTriggers.append(trigger)
 self.mazeGround = self.maze.find("**/ground_collide")
    self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1))
 self.ballRoot = render.attachNewNode("ballRoot")
    self.ball = loader.loadModel("models/ball")
    self.ball.reparentTo(self.ballRoot)
 self.ballSphere = self.ball.find("**/ball")
    self.ballSphere.node().setFromCollideMask(BitMask32.bit(0))
    self.ballSphere.node().setIntoCollideMask(BitMask32.allOff())

self.ballGroundRay = CollisionRay()     # Create the ray
    self.ballGroundRay.setOrigin(0,0,10)    # Set its origin
    self.ballGroundRay.setDirection(0,0,-1) # And its direction
    # Collision solids go in CollisionNode
    self.ballGroundCol = CollisionNode('groundRay') # Create and name the node
    self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray
    self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) # Set its bitmasks
    self.ballGroundCol.setIntoCollideMask(BitMask32.allOff())

 self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol)
    # Uncomment this line to see the ray
    # self.ballGroundColNp.show()

    # Finally, we create a CollisionTraverser. CollisionTraversers are what
    # do the job of calculating collisions
    self.cTrav = CollisionTraverser()

self.cHandler = CollisionHandlerQueue()
    # 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
    self.cTrav.addCollider(self.ballSphere, self.cHandler)
    self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)

    # Collision traversers have a built in tool to help visualize collisions.
    # Uncomment the next line to see it.
    # self.cTrav.showCollisions(render)
    
    # This section deals with lighting for the ball. Only the ball was lit
    # because the maze has static lighting pregenerated by the modeler
    ambientLight = AmbientLight("ambientLight")
    ambientLight.setColor(Vec4(.55, .55, .55, 1))
    directionalLight = DirectionalLight("directionalLight")
    directionalLight.setDirection(Vec3(0, 0, -1))
    directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1))
    directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
    self.ballRoot.setLight(render.attachNewNode(ambientLight))
    self.ballRoot.setLight(render.attachNewNode(directionalLight))
    
    # This section deals with adding a specular highlight to the ball to make
    # it look shiny
    m = Material()
    m.setSpecular(Vec4(1,1,1,1))
    m.setShininess(96)
    self.ball.setMaterial(m, 1)

self.start()

  def start(self):
    # The maze model also has a locator in it for where to start the ball
    # To access it we use the find command
    startPos = self.maze.find("**/start").getPos()
    self.ballRoot.setPos(startPos)   # Set the ball in the starting position
    self.ballV = Vec3(0,0,0)         # Initial velocity is 0
    self.accelV = Vec3(0,0,0)        # Initial acceleration is 0
    
    # For a traverser to actually do collisions, you need to call
    # traverser.traverse() on a part of the scene. Fortunatly, base has a
    # task that does this for the entire scene once a frame. This sets up our
    # traverser as the one to be called automatically
    base.cTrav = self.cTrav

    # Create the movement task, but first make sure it is not already running
    taskMgr.remove("rollTask")
    self.mainLoop = taskMgr.add(self.rollTask, "rollTask")
    self.mainLoop.last = 0

  # This function handles the collision between the ray and the ground
  # Information about the interaction is passed in colEntry
  def groundCollideHandler(self, colEntry):
    # Set the ball to the appropriate Z value for it to be exactly on the ground
    newZ = colEntry.getSurfacePoint(render).getZ()
    self.ballRoot.setZ(newZ+.4)

norm = colEntry.getSurfaceNormal(render)
    accelSide = norm.cross(UP)
    # Then that vector is crossed with the surface normal to get a vector that
    # points down the slope. By getting the acceleration in 3D like this rather
    # than in 2D, we reduce the amount of error per-frame, reducing jitter
    self.accelV = norm.cross(accelSide)

  # This function handles the collision between the ball and a wall
  def wallCollideHandler(self, colEntry):
    # First we calculate some numbers we need to do a reflection
    norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the wall
    curSpeed = self.ballV.length()                # The current speed
    inVec = self.ballV / curSpeed                 # The direction of travel
    velAngle = norm.dot(inVec)                    # Angle of incidance
    hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos()
    hitDir.normalize()                            
    hitAngle = norm.dot(hitDir)   # The angle between the ball and the normal

    # Ignore the collision if the ball is either moving away from the wall
    # already (so that we don't accidentally send it back into the wall)
    # and ignore it if the collision isn't dead-on (to avoid getting caught on
    # corners)
    if velAngle > 0 and hitAngle > .995:
      # Standard reflection equation
      reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec
        
      # This makes the velocity half of what it was if the hit was dead-on
      # and nearly exactly what it was if this is a glancing blow
      self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5))

disp = (colEntry.getSurfacePoint(render) -
              colEntry.getInteriorPoint(render))
      newPos = self.ballRoot.getPos() + disp
      self.ballRoot.setPos(newPos)

  # This is the task that deals with making everything interactive
  def rollTask(self, task):
    # Standard technique for finding the amount of time since the last frame
    dt = task.time - task.last
    task.last = task.time

    # If dt is large, then there has been a # hiccup that could cause the ball
    # to leave the field if this functions runs, so ignore the frame
    if dt > .2: return Task.cont   

    # The collision handler collects the collisions. We dispatch which function
    # to handle the collision based on the name of what was collided into
    for i in range(self.cHandler.getNumEntries()):
      entry = self.cHandler.getEntry(i)
      name = entry.getIntoNode().getName()
      if   name == "wall_collide":   self.wallCollideHandler(entry)
      elif name == "ground_collide": self.groundCollideHandler(entry)
      elif name == "loseTrigger":    self.loseGame(entry)

    # Read the mouse position and tilt the maze accordingly
    if base.mouseWatcherNode.hasMouse():
      mpos = base.mouseWatcherNode.getMouse() # get the mouse position
      self.maze.setP(mpos.getY() * -10)
      self.maze.setR(mpos.getX() * 10)

    # Finally, we move the ball
    # Update the velocity based on acceleration
    self.ballV += self.accelV * dt * ACCEL
    # Clamp the velocity to the maximum speed
    if self.ballV.lengthSquared() > MAX_SPEED_SQ:

self.ballV.normalize()
      self.ballV *= MAX_SPEED
    # Update the position based on the velocity
    self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV * dt))

    # This block of code rotates the ball. It uses something called a quaternion
    # to rotate the ball around an arbitrary axis. That axis perpendicular to
    # the balls rotation, and the amount has to do with the size of the ball
    # This is multiplied on the previous rotation to incrimentally turn it.
    prevRot = LRotationf(self.ball.getQuat())
    axis = UP.cross(self.ballV)
    newRot = LRotationf(axis, 45.5 * dt * self.ballV.length())
    self.ball.setQuat(prevRot * newRot)
    
    return Task.cont       # Continue the task indefinitely

  # If the ball hits a hole trigger, then it should fall in the hole.
  # This is faked rather than dealing with the actual physics of it.
  def loseGame(self, entry):
    # The triggers are set up so that the center of the ball should move to the
    # collision point to be in the hole
    toPos = entry.getInteriorPoint(render)
    taskMgr.remove('rollTask')  # Stop the maze task

    # Move the ball into the hole over a short sequence of time. Then wait a
    # second and call start to reset the game
    Sequence(
      Parallel(
      LerpFunc(self.ballRoot.setX, fromData = self.ballRoot.getX(),
               toData = toPos.getX(), duration = .1),
      LerpFunc(self.ballRoot.setY, fromData = self.ballRoot.getY(),
               toData = toPos.getY(), duration = .1),
      LerpFunc(self.ballRoot.setZ, fromData = self.ballRoot.getZ(),
               toData = self.ballRoot.getZ() - .9, duration = .2)),
      Wait(1),
 Func(self.start)).start()

# Finally, create an instance of our class and start 3d rendering
w = World()
run()

Try the Roaming Ralph in C++ example at the forums.

I already try it… but i can’t see any programming about C++ inside there? I run it and I try oso load a model of panda… then i try myself to create a collision detection between panda and the actor.
Here is my code…


// This is a C++ translation of the original Roaming Ralph example by Ryan Myers
// Models by Jeff Styers and Reagan Heller


// This tutorial provides an example of creating a character
// and having it walk around on uneven terrain, as well
// as implementing a fully rotatable camera.


#include "pandaFramework.h"

#include "pandaSystem.h"

#include "textNode.h"

#include "auto_bind.h"

#include "partGroup.h"

#include "animControlCollection.h"

#include "collisionTraverser.h"

#include "collisionRay.h"

#include "collisionNode.h"

#include "collisionHandlerQueue.h"

#include "collisionSphere.h"

#include "boundingSphere.h"

#include "nodePath.h"

#include "collisionHandlerEvent.h"


#include "cIntervalManager.h"
#include "cLerpNodePathInterval.h"
#include "cMetaInterval.h"



// Create an instance of the PandaFramework class
PandaFramework framework;

map<string,bool> key_map; // To store mapped keys


// Function declaration


void centry_sortz(pvector <PT(CollisionEntry)> &array, NodePath relative_to);



// Function to put instructions on the screen.

NodePath add_instructions(const float pos,const string msg,WindowFramework *win_ptr) {
  
PT(TextNode) tn = new TextNode("instructions");
  
tn->set_text(msg);
  NodePath tnp (win_ptr->get_aspect_2d().attach_new_node(tn));
  tnp.set_pos(-1.3,0,pos);
  tnp.set_scale(0.05);
  return tnp;
}

// Function to put title on the screen.
NodePath add_title(const string text,WindowFramework *win_ptr) {
  PT(TextNode) tn = new TextNode("title");
  tn->set_text(text);
  tn->set_align(TextNode::A_right);
  NodePath tnp (win_ptr->get_aspect_2d().attach_new_node(tn));
  tnp.set_pos(1.3,0,-0.95);
  tnp.set_scale(0.07);
  return tnp;
}

void exit_event(const Event * theEvent, void * data) {
  exit(0);
}

class World {
  public:
    PandaFramework *framework_ptr; // Keep a pointer to the framework
    WindowFramework *win_ptr; // Keep a pointer to the window
    NodePath camera; // Keep a nodepath to the camera, for convenience

    World(WindowFramework *window);
    static void set_key(const Event * theEvent, void * data);
    static void unset_key(const Event * theEvent, void * data);
    void move(double time);

    NodePath environ;
    NodePath ralph;
    AnimControlCollection ralph_anims;
    NodePath floater;
    NodePath title;
    NodePath inst1;
    NodePath inst2;
    NodePath inst3;
    NodePath inst4;
    NodePath inst5;
    NodePath inst6;
    NodePath inst7;
    double prevtime;
    bool is_moving;
    CollisionTraverser c_trav; // The traverser is NOT reference counted, while the other Collision-classes are.
    PT(CollisionRay) ralph_ground_ray;
    PT(CollisionNode) ralph_ground_col;
    NodePath ralph_ground_col_np;
    PT(CollisionHandlerQueue) ralph_ground_handler;
    PT(CollisionRay) cam_ground_ray;
    PT(CollisionNode) cam_ground_col;
    NodePath cam_ground_col_np;
    PT(CollisionHandlerQueue) cam_ground_handler;
	PT(CollisionHandlerEvent)  pandaActor_handler;
	PT(CollisionEntry) entry ; 
};
World::World(WindowFramework *window) {
  win_ptr=window;
  framework_ptr=win_ptr->get_panda_framework();
  camera = win_ptr->get_camera_group(); // Get the camera and store it, for convenience

  key_map["left"]=false;
  key_map["right"]=false;
  key_map["forward"]=false;
  key_map["cam-left"]=false;
  key_map["cam-right"]=false;
  win_ptr->get_graphics_window()->get_active_display_region(0)->set_clear_color(Colorf(0,0,0,1));

  // Post the instructions

  title = add_title("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)",win_ptr);
  inst1 = add_instructions(0.95, "[ESC]: Quit",win_ptr);
  inst2 = add_instructions(0.90, "[Left Arrow]: Rotate Ralph Left",win_ptr);
  inst3 = add_instructions(0.85, "[Right Arrow]: Rotate Ralph Right",win_ptr);
  inst4 = add_instructions(0.80, "[Up Arrow]: Run Ralph Forward",win_ptr);
  inst6 = add_instructions(0.70, "[A]: Rotate Camera Left",win_ptr);
  inst7 = add_instructions(0.65, "[S]: Rotate Camera Right",win_ptr);

  // 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.
  */
  environ = win_ptr->load_model(win_ptr->get_render(),"models/world.egg.pz");
  environ.reparent_to(win_ptr->get_render());
  environ.set_pos(0,0,0);

   // Load our panda
    NodePath pandaActor = window->load_model(framework.get_models(), "panda-model");
    pandaActor.set_scale(0.005);
	pandaActor.set_pos(-100,0,0);
    pandaActor.reparent_to(window->get_render());
 
    // Load the walk animation
    window->load_model(pandaActor, "panda-walk4");
    window->loop_animations(0);

	//collision panda
	NodePath pandaActor_Node_np;
	PT(CollisionSphere) pandaActor_solid = new CollisionSphere(0, 0, 200, 300);
	//cs = CollisionSphere(0, 0, 0, 1);

	PT(CollisionNode) pandaActor_Node = new CollisionNode("Sphere");
	pandaActor_Node->add_solid(pandaActor_solid);
	pandaActor_Node_np = pandaActor.attach_new_node(pandaActor_Node);
	pandaActor_Node_np.show();
    entry  = new PT(CollisionEntry); 
 // Create the lerp intervals needed to walk back and forth
  PT(CLerpNodePathInterval) pandaPosInterval1, pandaPosInterval2,
    pandaHprInterval1, pandaHprInterval2;
  pandaPosInterval1 = new CLerpNodePathInterval("pandaPosInterval1",
    5.0, CLerpInterval::BT_no_blend,
    true, false, pandaActor, NodePath());
  pandaPosInterval1->set_start_pos(LPoint3f(-100, 10, 0));
  pandaPosInterval1->set_end_pos(LPoint3f(-100, -50, 0));
 
  pandaPosInterval2 = new CLerpNodePathInterval("pandaPosInterval2",
    5.0, CLerpInterval::BT_no_blend,
    true, false, pandaActor, NodePath());
  pandaPosInterval2->set_start_pos(LPoint3f(-100, -50, 0));
  pandaPosInterval2->set_end_pos(LPoint3f(-100, 10, 0));
 
  pandaHprInterval1 = new CLerpNodePathInterval("pandaHprInterval1", 3.0,
    CLerpInterval::BT_no_blend,
    true, false, pandaActor, NodePath());
  pandaHprInterval1->set_start_hpr(LPoint3f(0, 0, 0));
  pandaHprInterval1->set_end_hpr(LPoint3f(180, 0, 0));
 
  pandaHprInterval2 = new CLerpNodePathInterval("pandaHprInterval2", 3.0,
    CLerpInterval::BT_no_blend,
    true, false, pandaActor, NodePath());
  pandaHprInterval2->set_start_hpr(LPoint3f(180, 0, 0));
  pandaHprInterval2->set_end_hpr(LPoint3f(0, 0, 0));
 
  // Create and play the sequence that coordinates the intervals
  PT(CMetaInterval) pandaPace;
  pandaPace = new CMetaInterval("pandaPace");
  pandaPace->add_c_interval(pandaPosInterval1, 0,
    CMetaInterval::RS_previous_end);
  pandaPace->add_c_interval(pandaHprInterval1, 0,
    CMetaInterval::RS_previous_end);
  pandaPace->add_c_interval(pandaPosInterval2, 0,
    CMetaInterval::RS_previous_end);
  pandaPace->add_c_interval(pandaHprInterval2, 0,
    CMetaInterval::RS_previous_end);
  pandaPace->loop();

  
  // Create the main character, Ralph

  LPoint3f ralph_start_pos (environ.find("**/start_point").get_pos());
 ralph = win_ptr->load_model(framework_ptr->get_models(),"models/ralph.egg.pz");
   ralph.set_scale(0.2);
  ralph.set_pos(ralph_start_pos);
  ralph.reparent_to(win_ptr->get_render());

  // Load Ralph's animations

   win_ptr->load_model(ralph,"models/ralph-walk.egg.pz");
  win_ptr->load_model(ralph,"models/ralph-run.egg.pz");
  auto_bind(ralph.node(), ralph_anims, PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name);

  // Create a floater object.  We use the "floater" as a temporary
  // variable in a variety of calculations.
  PT(PandaNode) floaterNode = new PandaNode("floater");
  floater=window->get_render().attach_new_node(floaterNode);
  floater.reparent_to(window->get_render());

  // Accept the control keys for movement and rotation

  framework_ptr->define_key("escape", "Quit", exit_event, 0);
  char* data;
  data="left";      framework_ptr->define_key("arrow_left", "Rotate Ralph Left", set_key, (void *) data);
  data="right";     framework_ptr->define_key("arrow_right", "Rotate Ralph Right", set_key, (void *) data);
  data="forward";   framework_ptr->define_key("arrow_up", "Run Ralph Forward", set_key, (void *) data);
  data="cam-left";  framework_ptr->define_key("a", "Rotate Camera Left", set_key, (void *) data);
  data="cam-right"; framework_ptr->define_key("s", "Rotate Camera Right", set_key, (void *) data);
  data="left";      framework_ptr->define_key("arrow_left-up", "Rotate Ralph Left", unset_key, (void *) data);
  data="right";     framework_ptr->define_key("arrow_right-up", "Rotate Ralph Right", unset_key, (void *) data);
  data="forward";   framework_ptr->define_key("arrow_up-up", "Run Ralph Forward", unset_key, (void *) data);
  data="cam-left";  framework_ptr->define_key("a-up", "Rotate Camera Left", unset_key, (void *) data);
  data="cam-right"; framework_ptr->define_key("s-up", "Rotate Camera Right", unset_key, (void *) data);

  // Game state variables

  prevtime = 0.0;
  is_moving = false;

  // Set up the camera

  camera.set_pos(ralph.get_x(),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.
  
  ralph_ground_ray = new CollisionRay();
  ralph_ground_ray->set_origin(0,0,1000);
  ralph_ground_ray->set_direction(0,0,-1);
  ralph_ground_col = new CollisionNode("ralph_ray");
  ralph_ground_col->add_solid(ralph_ground_ray);
  ralph_ground_col->set_from_collide_mask(BitMask32::bit(0));
  ralph_ground_col->set_into_collide_mask(BitMask32::all_off());
  ralph_ground_col_np = ralph.attach_new_node(ralph_ground_col);
  ralph_ground_handler = new CollisionHandlerQueue();
  c_trav.add_collider(ralph_ground_col_np, ralph_ground_handler);

  cam_ground_ray = new CollisionRay();
  cam_ground_ray->set_origin(0,0,1000);
  cam_ground_ray->set_direction(0,0,-1);
  cam_ground_col = new CollisionNode("cam_ray");
  cam_ground_col->add_solid(cam_ground_ray);
  cam_ground_col->set_from_collide_mask(BitMask32::bit(0));
  cam_ground_col->set_into_collide_mask(BitMask32::all_off());
  cam_ground_col_np = camera.attach_new_node(cam_ground_col);
  cam_ground_handler = new CollisionHandlerQueue();
  c_trav.add_collider(cam_ground_col_np, cam_ground_handler);

  // Uncomment this line to see the collision rays
  ralph_ground_col_np.show();
  cam_ground_col_np.show();
 
  // Uncomment this line to show a visual representation of the collisions occuring
  c_trav.show_collisions(win_ptr->get_render());

  //collision handler
//PT( CollisionHandlerQueue) pandaActor_handler = new CollisionHandlerQueue();
//c_trav.add_collider(pandaActor_Node_np,pandaActor_handler);

//for(int i = 1; i<=queue.get_num_entries();i++)
//{
//            int entry;
//			entry = queue.get_entry(i);
//            cout<<entry;
//}
//PT( CollisionHandlerEvent) C_handler = new CollisionHandlerEvent();
pandaActor_handler = new CollisionHandlerEvent();
pandaActor_handler->add_in_pattern("yes");
pandaActor_handler->add_again_pattern("yes");
pandaActor_handler->add_out_pattern("no");

}
void World::set_key(const Event * theEvent, void * data) {
  char *key = (char *) data;
  key_map[key]=true;
}
void World::unset_key(const Event * theEvent, void * data) {
  char *key = (char *) data;
  key_map[key]=false;
}
void World::move(double time) {

  double elapsed (time-prevtime);

  // If the camera-left key is pressed, move camera left.
  // If the camera-right key is pressed, move camera right.

  camera.look_at(ralph);
  LVecBase3f camright (camera.get_net_transform()->get_mat().get_row3(0));
  camright.normalize();
  if(key_map["cam-left"]) {
    camera.set_pos(camera.get_pos() - camright*(elapsed*20.0));
  }
  if(key_map["cam-right"]) {
    camera.set_pos(camera.get_pos() + camright*(elapsed*20.0));
  }

  // save ralph's initial position so that we can restore it,
  // in case he falls off the map or runs into something.

  LPoint3f startpos (ralph.get_pos());

  // If a move-key is pressed, move ralph in the specified direction.

  if(key_map["left"]) {
    ralph.set_h(ralph.get_h() + elapsed*300.0);
  }
  if(key_map["right"]) {
    ralph.set_h(ralph.get_h() - elapsed*300.0);
  }
  if(key_map["forward"]) {
    LVecBase3f backward (ralph.get_net_transform()->get_mat().get_row3(1));
    backward.set_z(0);
    backward.normalize();
    ralph.set_pos(ralph.get_pos() - backward*(elapsed*5.0));
  }

  // If ralph is moving, loop the run animation.
  // If he is standing still, stop the animation.

  if(key_map["forward"] || key_map["left"] || key_map["right"]) {
    if(! is_moving) {
      ralph_anims.loop("Ralph.1",false);
      is_moving=true;
    }
  } else {
    if(is_moving) {
      ralph_anims.stop_all();
      ralph_anims.pose("Ralph",5);
      is_moving=false;
    }
  }

  // If the camera is too far from ralph, move it closer.
  // If the camera is too close to ralph, move it farther.

  LVecBase3f camvec (ralph.get_pos() - camera.get_pos());
  camvec.set_z(0);
  float camdist (camvec.length());
  camvec.normalize();
  if(camdist > 10.0) {
    camera.set_pos(camera.get_pos() + camvec*(camdist-10.0));
    camdist = 10.0;
  }
  if(camdist < 5.0) {
    camera.set_pos(camera.get_pos() - camvec*(5.0-camdist));
    camdist = 5.0;
  }
 
  // Now check for collisions.

  c_trav.traverse(win_ptr->get_render());
  
  // Adjust ralph's Z coordinate.  If ralph's ray hit terrain,
  // update his Z. If it hit anything else, or didn't hit anything, put
  // him back where he was last frame.

  pvector <PT(CollisionEntry)> *entries; // Create a vector to store entries in
  entries = new pvector <PT(CollisionEntry)>;
  for(unsigned int i = 0; i < ralph_ground_handler->get_num_entries(); i++) {
    entries->push_back(ralph_ground_handler->get_entry(i));
  }
  centry_sortz(*entries,win_ptr->get_render()); // Sort the entries by Z-position
  if(entries->size()>0 && entries->front()->get_into_node()->get_name() == "terrain") {
    ralph.set_z(entries->front()->get_surface_point(win_ptr->get_render()).get_z());
  } else {
    ralph.set_pos(startpos);
  }
  
  // Keep the camera at one foot above the terrain,
  // or two feet above ralph, whichever is greater.

  entries->clear();
  for(unsigned int i = 0; i < cam_ground_handler->get_num_entries(); i++) {
    entries->push_back(cam_ground_handler->get_entry(i));
  }
  centry_sortz(*entries,win_ptr->get_render()); // Sort the entries by Z-position
  if(entries->size()>0 && entries->front()->get_into_node()->get_name() == "terrain") {
    camera.set_z(entries->front()->get_surface_point(win_ptr->get_render()).get_z() + 1.0);
  }
  if(camera.get_z() < ralph.get_z() + 2.0) {
    camera.set_z(ralph.get_z() + 2.0);
  }

  //Ralph collision with panda
  /*if(entry->get_into_node_path()=="PandaActor_node")
{
	cout<<"anything";
}*/
  cout << entry->get_into_node_path();
  
      
  // The camera should look in ralph's direction,
  // but it should also try to stay horizontal, so look at
  // a floater which hovers above ralph's head.
  
  floater.set_pos(ralph.get_pos());
  floater.set_z(ralph.get_z() + 2.0);
  camera.look_at(floater); 

  // Store the task time and continue.
  prevtime = time;

}

int main(int argc, char *argv[]) {
  framework.open_framework(argc, argv);
  framework.set_window_title("Roaming Ralph");
  WindowFramework *window = framework.open_window();
  // Check whether the window was opened right
  if (window != (WindowFramework *)NULL) {
    window->enable_keyboard();
    ClockObject* clock;
    clock=ClockObject::get_global_clock();
    World w(window);
    // Main loop:
    Thread *current_thread = Thread::get_current_thread();
    while(framework.do_frame(current_thread)) {
		CIntervalManager::get_global_ptr()->step();
      w.move(clock->get_real_time()); // Call the move function of the world
    }
  } else {
    nout << "Could not load the window!\n";
  }
  
  framework.close_framework();
  return (0);
}
// This function sorts collisionentries, I just directly grabbed it from the internet
void centry_sortz(pvector <PT(CollisionEntry)> &array, NodePath relative_to)
{
  int i, j, flag = 1;    // set flag to 1 to begin initial pass
  PT(CollisionEntry) temp;             // holding variable
  int arrayLength = array.size();
  for(i = 1; (i <= arrayLength) && flag; i++)
  {
    flag = 0;
    for (j=0; j < (arrayLength -1); j++)
    {
      if (array[j+1]->get_surface_point(relative_to).get_z() > array[j]->get_surface_point(relative_to).get_z())
      { 
        temp = array[j];             // swap elements
        array[j] = array[j+1];
        array[j+1] = temp;
        flag = 1;               // indicates that a swap occurred.
      }
    }
 }
 return;   //arrays are passed to functions by address; nothing is returned
}

From the source code above, who can show me how to create collision detection to the actor and the panda model… Plz show some line of collision detection…