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.walls = self.maze.find("**/wall_collide")
self.loseTriggers = []
    for i in range(6):
      trigger = self.maze.find("**/hole_collide" + str(i))
 self.mazeGround = self.maze.find("**/ground_collide")
 self.ballRoot = render.attachNewNode("ballRoot")
    self.ball = loader.loadModel("models/ball")
 self.ballSphere = self.ball.find("**/ball")

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.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol)
    # Uncomment this line to see the ray

    # 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))
    # This section deals with adding a specular highlight to the ball to make
    # it look shiny
    m = Material()
    self.ball.setMaterial(m, 1)


  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
    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()

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 =                    # Angle of incidance
    hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos()
    hitAngle =   # 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 * * -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) -
      newPos = self.ballRoot.getPos() + disp

  # 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 *= 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
      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)),

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

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");
  NodePath tnp (win_ptr->get_aspect_2d().attach_new_node(tn));
  return tnp;

// Function to put title on the screen.
NodePath add_title(const string text,WindowFramework *win_ptr) {
  PT(TextNode) tn = new TextNode("title");
  NodePath tnp (win_ptr->get_aspect_2d().attach_new_node(tn));
  return tnp;

void exit_event(const Event * theEvent, void * data) {

class World {
    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) {
  camera = win_ptr->get_camera_group(); // Get the camera and store it, for convenience


  // 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");

   // Load our panda
    NodePath pandaActor = window->load_model(framework.get_models(), "panda-model");
    // Load the walk animation
    window->load_model(pandaActor, "panda-walk4");

	//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_np = pandaActor.attach_new_node(pandaActor_Node);;
    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,
    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,
    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,
  pandaPace->add_c_interval(pandaHprInterval1, 0,
  pandaPace->add_c_interval(pandaPosInterval2, 0,
  pandaPace->add_c_interval(pandaHprInterval2, 0,

  // 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");

  // Load Ralph's animations

  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");

  // 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


  // 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_col = new CollisionNode("ralph_ray");
  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_col = new CollisionNode("cam_ray");
  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;;
  // Uncomment this line to show a visual representation of the collisions occuring

  //collision handler
//PT( CollisionHandlerQueue) pandaActor_handler = new CollisionHandlerQueue();

//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();

void World::set_key(const Event * theEvent, void * data) {
  char *key = (char *) data;
void World::unset_key(const Event * theEvent, void * data) {
  char *key = (char *) data;
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.

  LVecBase3f camright (camera.get_net_transform()->get_mat().get_row3(0));
  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));
    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) {
  } else {
    if(is_moving) {

  // 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());
  float camdist (camvec.length());
  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.

  // 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++) {
  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") {
  } else {
  // Keep the camera at one foot above the terrain,
  // or two feet above ralph, whichever is greater.

  for(unsigned int i = 0; i < cam_ground_handler->get_num_entries(); 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
  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_z(ralph.get_z() + 2.0);

  // 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) {
    ClockObject* clock;
    World w(window);
    // Main loop:
    Thread *current_thread = Thread::get_current_thread();
    while(framework.do_frame(current_thread)) {
      w.move(clock->get_real_time()); // Call the move function of the world
  } else {
    nout << "Could not load the window!\n";
  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…