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