abstract out PandaFramework etc.
This commit is contained in:
parent
ca6b643da5
commit
e286a73dbb
|
|
@ -1,38 +1,20 @@
|
|||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
|
||||
#begin static_lib_target
|
||||
#begin lib_target
|
||||
#define TARGET framework
|
||||
#define BUILDING_DLL BUILDING_FRAMEWORK
|
||||
#define LOCAL_LIBS \
|
||||
putil collide loader sgmanip chan text chancfg cull \
|
||||
pgraph putil collide loader sgmanip chan text chancfg cull \
|
||||
pnmimage pnmimagetypes event
|
||||
|
||||
#define SOURCES \
|
||||
config_framework.cxx config_framework.h framework.cxx framework.h
|
||||
config_framework.cxx config_framework.h \
|
||||
pandaFramework.cxx pandaFramework.I pandaFramework.h \
|
||||
windowFramework.cxx windowFramework.I windowFramework.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
framework.h
|
||||
|
||||
#end static_lib_target
|
||||
|
||||
|
||||
#if $[HAVE_DX]
|
||||
// USE_DX ensures DirectX dirs are on include&link lines
|
||||
#define USE_DX yes
|
||||
|
||||
#begin static_lib_target
|
||||
#define TARGET framework_multimon
|
||||
#define LOCAL_LIBS \
|
||||
putil collide loader sgmanip chan text chancfg cull \
|
||||
pnmimage pnmimagetypes event wdxdisplay
|
||||
|
||||
#define SOURCES \
|
||||
config_framework.cxx config_framework.h framework_multimon.cxx framework.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
framework.h
|
||||
|
||||
#end static_lib_target
|
||||
#endif
|
||||
|
||||
pandaFramework.I pandaFramework.h \
|
||||
windowFramework.I windowFramework.h
|
||||
|
||||
#end lib_target
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ NotifyCategoryDef(framework, "");
|
|||
ConfigureFn(config_framework) {
|
||||
}
|
||||
|
||||
// This is the height above the ground your eye should maintain while
|
||||
// driving using the "D" interface.
|
||||
const double drive_height = config_framework.GetDouble("drive-height", 6.0);
|
||||
const CollideMask drive_mask = config_framework.GetInt("drive-mask", ~0);
|
||||
const int win_width = config_framework.GetInt("win-width", 640);
|
||||
const int win_height = config_framework.GetInt("win-height", 480);
|
||||
const bool fullscreen = config_framework.GetBool("fullscreen", false);
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@
|
|||
#ifndef CONFIG_FRAMEWORK_H
|
||||
#define CONFIG_FRAMEWORK_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <notifyCategoryProxy.h>
|
||||
#include <collideMask.h>
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
|
||||
NotifyCategoryDecl(framework, EXPCL_EMPTY, EXPCL_EMPTY);
|
||||
NotifyCategoryDecl(framework, EXPCL_FRAMEWORK, EXPCL_FRAMEWORK);
|
||||
|
||||
// Configure variables for framework package.
|
||||
extern const double drive_height;
|
||||
extern const CollideMask drive_mask;
|
||||
extern const int win_width;
|
||||
extern const int win_height;
|
||||
extern const bool fullscreen;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
// Filename: pandaFramework.I
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_graphics_engine
|
||||
// Access: Public
|
||||
// Description: Returns the GraphicsEngine that is used to render all
|
||||
// the windows in the framework. Normally there's no
|
||||
// reason for user code to mess with this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsEngine *PandaFramework::
|
||||
get_graphics_engine() {
|
||||
return &_engine;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_data_root
|
||||
// Access: Public
|
||||
// Description: Returns the root of the data graph. This is the
|
||||
// graph of nodes that is traversed to control the
|
||||
// inputs from user devices like the mouse and keyboard.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const qpNodePath &PandaFramework::
|
||||
get_data_root() const {
|
||||
return _data_root;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_event_handler
|
||||
// Access: Public
|
||||
// Description: Returns the EventHandler object that serves events in
|
||||
// the framework. This is primarily used to dispatch on
|
||||
// keypresses and such.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EventHandler &PandaFramework::
|
||||
get_event_handler() {
|
||||
return _event_handler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_window_title
|
||||
// Access: Public
|
||||
// Description: Specifies the title that is set for all subsequently
|
||||
// created windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaFramework::
|
||||
set_window_title(const string &title) {
|
||||
_window_title = title;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_num_windows
|
||||
// Access: Public
|
||||
// Description: Returns the number of windows that are currently
|
||||
// open.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PandaFramework::
|
||||
get_num_windows() const {
|
||||
return _windows.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_window
|
||||
// Access: Public
|
||||
// Description: Returns the nth window currently open.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE WindowFramework *PandaFramework::
|
||||
get_window(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_windows.size(), NULL);
|
||||
return _windows[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_wireframe
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the wireframe flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PandaFramework::
|
||||
get_wireframe() const {
|
||||
return _wireframe_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_texture
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the texture flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PandaFramework::
|
||||
get_texture() const {
|
||||
return _texture_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_two_sided
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the two_sided flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PandaFramework::
|
||||
get_two_sided() const {
|
||||
return _two_sided_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_lighting
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the lighting flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PandaFramework::
|
||||
get_lighting() const {
|
||||
return _lighting_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_exit_flag
|
||||
// Access: Public
|
||||
// Description: Sets the flag that indicates it is time for the
|
||||
// application to exit. The application will actually
|
||||
// exit at the end of the current frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaFramework::
|
||||
set_exit_flag() {
|
||||
_exit_flag = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,530 @@
|
|||
// Filename: pandaFramework.cxx
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaFramework.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatClient.h"
|
||||
#include "eventQueue.h"
|
||||
#include "qpdataGraphTraverser.h"
|
||||
#include "interactiveGraphicsPipe.h"
|
||||
#include "config_framework.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaFramework::
|
||||
PandaFramework() :
|
||||
_event_handler(EventQueue::get_global_event_queue())
|
||||
{
|
||||
_is_open = false;
|
||||
_made_default_pipe = false;
|
||||
_data_root = qpNodePath("data");
|
||||
_window_title = "Panda";
|
||||
_start_time = 0.0;
|
||||
_frame_count = 0;
|
||||
_wireframe_enabled = false;
|
||||
_texture_enabled = true;
|
||||
_two_sided_enabled = false;
|
||||
_lighting_enabled = false;
|
||||
_default_keys_enabled = false;
|
||||
_exit_flag = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaFramework::
|
||||
~PandaFramework() {
|
||||
if (_is_open) {
|
||||
close_framework();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::open_framework
|
||||
// Access: Public
|
||||
// Description: Should be called once at the beginning of the
|
||||
// application to initialize Panda (and the framework)
|
||||
// for use. The command-line arguments should be passed
|
||||
// in so Panda can remove any arguments that it
|
||||
// recognizes as special control parameters.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
open_framework(int &argc, char **&argv) {
|
||||
if (_is_open) {
|
||||
return;
|
||||
}
|
||||
|
||||
_is_open = true;
|
||||
|
||||
reset_frame_rate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::close_framework
|
||||
// Access: Public
|
||||
// Description: Should be called at the end of an application to
|
||||
// close Panda. This is optional, as the destructor
|
||||
// will do the same thing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
close_framework() {
|
||||
if (!_is_open) {
|
||||
return;
|
||||
}
|
||||
|
||||
close_all_windows();
|
||||
// We should define this function on GraphicsEngine.
|
||||
// _engine.remove_all_windows();
|
||||
_event_handler.remove_all_hooks();
|
||||
|
||||
_is_open = false;
|
||||
_made_default_pipe = false;
|
||||
_default_pipe.clear();
|
||||
|
||||
_start_time = 0.0;
|
||||
_frame_count = 0;
|
||||
_wireframe_enabled = false;
|
||||
_two_sided_enabled = false;
|
||||
_lighting_enabled = false;
|
||||
_default_keys_enabled = false;
|
||||
_exit_flag = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_default_pipe
|
||||
// Access: Public
|
||||
// Description: Returns the default pipe. This is the GraphicsPipe
|
||||
// that all windows in the framework will be created on,
|
||||
// unless otherwise specified in open_window(). It is
|
||||
// usually the primary graphics interface on the local
|
||||
// machine.
|
||||
//
|
||||
// If the default pipe has not yet been created, this
|
||||
// creates it.
|
||||
//
|
||||
// The return value is the default pipe, or NULL if no
|
||||
// default pipe could be created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsPipe *PandaFramework::
|
||||
get_default_pipe() {
|
||||
nassertr(_is_open, NULL);
|
||||
if (!_made_default_pipe) {
|
||||
make_default_pipe();
|
||||
_made_default_pipe = true;
|
||||
}
|
||||
return _default_pipe;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_default_window_props
|
||||
// Access: Public, Virtual
|
||||
// Description: Fills in the indicated window properties structure
|
||||
// according to the normal window properties for this
|
||||
// application.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
get_default_window_props(GraphicsWindow::Properties &props) {
|
||||
props._xorg = 0;
|
||||
props._yorg = 0;
|
||||
props._xsize = win_width;
|
||||
props._ysize = win_height;
|
||||
props._fullscreen = fullscreen;
|
||||
props._title = _window_title;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::open_window
|
||||
// Access: Public
|
||||
// Description: Opens a new window, using the default parameters.
|
||||
// Returns the new WindowFramework if successful, or
|
||||
// NULL if not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
WindowFramework *PandaFramework::
|
||||
open_window(GraphicsPipe *pipe) {
|
||||
nassertr(_is_open, NULL);
|
||||
|
||||
GraphicsWindow::Properties props;
|
||||
get_default_window_props(props);
|
||||
|
||||
return open_window(props, pipe);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::open_window
|
||||
// Access: Public
|
||||
// Description: Opens a new window using the indicated properties.
|
||||
// (You may initialize the properties to their default
|
||||
// values by calling get_default_window_props() first.)
|
||||
//
|
||||
// Returns the new WindowFramework if successful, or
|
||||
// NULL if not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
WindowFramework *PandaFramework::
|
||||
open_window(const GraphicsWindow::Properties &props, GraphicsPipe *pipe) {
|
||||
if (pipe == (GraphicsPipe *)NULL) {
|
||||
pipe = get_default_pipe();
|
||||
if (pipe == (GraphicsPipe *)NULL) {
|
||||
// Can't get a pipe.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nassertr(_is_open, NULL);
|
||||
WindowFramework *wf = make_window_framework();
|
||||
_windows.push_back(wf);
|
||||
|
||||
GraphicsWindow *win = wf->open_window(props, pipe);
|
||||
if (win != (GraphicsWindow *)NULL) {
|
||||
_engine.add_window(win);
|
||||
}
|
||||
|
||||
return wf;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::close_window
|
||||
// Access: Public
|
||||
// Description: Closes the nth window and removes it from the list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
close_window(int n) {
|
||||
nassertv(n >= 0 && n < (int)_windows.size());
|
||||
WindowFramework *wf = _windows[n];
|
||||
|
||||
GraphicsWindow *win = wf->get_graphics_window();
|
||||
if (win != (GraphicsWindow *)NULL) {
|
||||
_engine.remove_window(win);
|
||||
}
|
||||
|
||||
wf->close_window();
|
||||
delete wf;
|
||||
_windows.erase(_windows.begin() + n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::close_all_windows
|
||||
// Access: Public
|
||||
// Description: Closes all currently open windows and empties the
|
||||
// list of windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
close_all_windows() {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
WindowFramework *wf = (*wi);
|
||||
|
||||
GraphicsWindow *win = wf->get_graphics_window();
|
||||
if (win != (GraphicsWindow *)NULL) {
|
||||
_engine.remove_window(win);
|
||||
}
|
||||
|
||||
wf->close_window();
|
||||
delete wf;
|
||||
}
|
||||
|
||||
_windows.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::report_frame_rate
|
||||
// Access: Public
|
||||
// Description: Reports the currently measured average frame rate to
|
||||
// the indicated ostream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
report_frame_rate(ostream &out) const {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
double delta = now - _start_time;
|
||||
|
||||
int frame_count = ClockObject::get_global_clock()->get_frame_count();
|
||||
int num_frames = frame_count - _frame_count;
|
||||
if (num_frames > 0) {
|
||||
out << num_frames << " frames in " << delta << " seconds.\n";
|
||||
double fps = ((double)num_frames) / delta;
|
||||
out << fps << " fps average (" << 1000.0 / fps << "ms)\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::reset_frame_rate
|
||||
// Access: Public
|
||||
// Description: Resets the frame rate computation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
reset_frame_rate() {
|
||||
_start_time = ClockObject::get_global_clock()->get_frame_time();
|
||||
_frame_count = ClockObject::get_global_clock()->get_frame_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_wireframe
|
||||
// Access: Public
|
||||
// Description: Sets the wireframe state on all windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
set_wireframe(bool enable) {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
WindowFramework *wf = (*wi);
|
||||
wf->set_wireframe(enable);
|
||||
}
|
||||
|
||||
_wireframe_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_texture
|
||||
// Access: Public
|
||||
// Description: Sets the texture state on all windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
set_texture(bool enable) {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
WindowFramework *wf = (*wi);
|
||||
wf->set_texture(enable);
|
||||
}
|
||||
|
||||
_texture_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_two_sided
|
||||
// Access: Public
|
||||
// Description: Sets the two_sided state on all windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
set_two_sided(bool enable) {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
WindowFramework *wf = (*wi);
|
||||
wf->set_two_sided(enable);
|
||||
}
|
||||
|
||||
_two_sided_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_lighting
|
||||
// Access: Public
|
||||
// Description: Sets the lighting state on all windows.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
set_lighting(bool enable) {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
WindowFramework *wf = (*wi);
|
||||
wf->set_lighting(enable);
|
||||
}
|
||||
|
||||
_lighting_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::enable_default_keys
|
||||
// Access: Public
|
||||
// Description: Sets callbacks on the event handler to handle all of
|
||||
// the normal viewer keys, like t to toggle texture, ESC
|
||||
// or q to quit, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
enable_default_keys() {
|
||||
if (!_default_keys_enabled) {
|
||||
do_enable_default_keys();
|
||||
_default_keys_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::do_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Renders one frame and performs all associated
|
||||
// processing. Returns true if we should continue
|
||||
// rendering, false if we should exit. This is normally
|
||||
// called only from main_loop().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaFramework::
|
||||
do_frame() {
|
||||
nassertr(_is_open, false);
|
||||
qpDataGraphTraverser dg_trav;
|
||||
dg_trav.traverse(_data_root.node());
|
||||
_event_handler.process_events();
|
||||
_engine.render_frame();
|
||||
|
||||
return !_exit_flag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::main_loop
|
||||
// Access: Public
|
||||
// Description: Called to yield control to the panda framework. This
|
||||
// function does not return until set_exit_flag() has
|
||||
// been called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
main_loop() {
|
||||
while (do_frame()) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::make_window_framework
|
||||
// Access: Protected, Virtual
|
||||
// Description: Creates a new WindowFramework object. This is
|
||||
// provided as a hook so derived PandaFramework classes
|
||||
// can create custom WindowFramework objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
WindowFramework *PandaFramework::
|
||||
make_window_framework() {
|
||||
return new WindowFramework(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::make_default_pipe
|
||||
// Access: Protected, Virtual
|
||||
// Description: Creates the default GraphicsPipe that will contain
|
||||
// all windows that are not opened on a specific pipe.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
make_default_pipe() {
|
||||
// We use the GraphicsPipe factory to make us a renderable pipe
|
||||
// without knowing exactly what kind of pipes we have available. We
|
||||
// don't care, so long as we can render to it interactively.
|
||||
|
||||
// This depends on the shared library or libraries (DLL's to you
|
||||
// Windows folks) that have been loaded in at runtime from the
|
||||
// load-display Configrc variable.
|
||||
GraphicsPipe::resolve_modules();
|
||||
|
||||
nout << "Known pipe types:" << endl;
|
||||
GraphicsPipe::get_factory().write_types(nout, 2);
|
||||
|
||||
_default_pipe = GraphicsPipe::get_factory().
|
||||
make_instance(InteractiveGraphicsPipe::get_class_type());
|
||||
|
||||
if (_default_pipe == (GraphicsPipe*)NULL) {
|
||||
nout << "No interactive pipe is available! Check your Configrc!\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::do_enable_default_keys
|
||||
// Access: Protected, Virtual
|
||||
// Description: The implementation of enable_default_keys().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
do_enable_default_keys() {
|
||||
_event_handler.add_hook("escape", event_esc, this);
|
||||
_event_handler.add_hook("q", event_esc, this);
|
||||
_event_handler.add_hook("f", event_f, this);
|
||||
_event_handler.add_hook("w", event_w, this);
|
||||
_event_handler.add_hook("t", event_t, this);
|
||||
_event_handler.add_hook("b", event_b, this);
|
||||
_event_handler.add_hook("l", event_l, this);
|
||||
_event_handler.add_hook("shift-s", event_S, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_esc
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for ESC or q key: exit the
|
||||
// application.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_esc(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->_exit_flag = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_f
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for f key: report and reset frame
|
||||
// rate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_f(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->report_frame_rate(nout);
|
||||
self->reset_frame_rate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_w
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for w key: toggle wireframe.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_w(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->set_wireframe(!self->get_wireframe());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_t
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for t key: toggle texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_t(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->set_texture(!self->get_texture());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_b
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for b key: toggle backface (two-sided
|
||||
// rendering).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_b(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->set_two_sided(!self->get_two_sided());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_l
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for l key: toggle lighting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_l(CPT_Event, void *data) {
|
||||
PandaFramework *self = (PandaFramework *)data;
|
||||
self->set_lighting(!self->get_lighting());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::event_S
|
||||
// Access: Protected, Static
|
||||
// Description: Default handler for shift-S key: activate stats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaFramework::
|
||||
event_S(CPT_Event, void *data) {
|
||||
#ifdef DO_PSTATS
|
||||
nout << "Connecting to stats host" << endl;
|
||||
PStatClient::connect();
|
||||
#else
|
||||
nout << "Stats host not supported." << endl;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
// Filename: pandaFramework.h
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PANDAFRAMEWORK_H
|
||||
#define PANDAFRAMEWORK_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "windowFramework.h"
|
||||
|
||||
#include "qpnodePath.h"
|
||||
#include "eventHandler.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "graphicsEngine.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaFramework
|
||||
// Description : This class serves to provide a high-level framework
|
||||
// for basic applications that use Panda in simple ways
|
||||
// (like opening a window to view models, etc.).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_FRAMEWORK PandaFramework {
|
||||
public:
|
||||
PandaFramework();
|
||||
virtual ~PandaFramework();
|
||||
|
||||
void open_framework(int &argc, char **&argv);
|
||||
void close_framework();
|
||||
|
||||
GraphicsPipe *get_default_pipe();
|
||||
INLINE GraphicsEngine *get_graphics_engine();
|
||||
INLINE const qpNodePath &get_data_root() const;
|
||||
INLINE EventHandler &get_event_handler();
|
||||
|
||||
INLINE void set_window_title(const string &title);
|
||||
virtual void get_default_window_props(GraphicsWindow::Properties &props);
|
||||
|
||||
WindowFramework *open_window(GraphicsPipe *pipe = NULL);
|
||||
WindowFramework *open_window(const GraphicsWindow::Properties &props,
|
||||
GraphicsPipe *pipe = NULL);
|
||||
|
||||
INLINE int get_num_windows() const;
|
||||
INLINE WindowFramework *get_window(int n) const;
|
||||
void close_window(int n);
|
||||
void close_all_windows();
|
||||
|
||||
void report_frame_rate(ostream &out) const;
|
||||
void reset_frame_rate();
|
||||
|
||||
void set_wireframe(bool enable);
|
||||
void set_texture(bool enable);
|
||||
void set_two_sided(bool enable);
|
||||
void set_lighting(bool enable);
|
||||
|
||||
INLINE bool get_wireframe() const;
|
||||
INLINE bool get_texture() const;
|
||||
INLINE bool get_two_sided() const;
|
||||
INLINE bool get_lighting() const;
|
||||
|
||||
void enable_default_keys();
|
||||
|
||||
virtual bool do_frame();
|
||||
void main_loop();
|
||||
|
||||
INLINE void set_exit_flag();
|
||||
|
||||
protected:
|
||||
virtual WindowFramework *make_window_framework();
|
||||
virtual void make_default_pipe();
|
||||
virtual void do_enable_default_keys();
|
||||
|
||||
static void event_esc(CPT_Event, void *data);
|
||||
static void event_f(CPT_Event, void *data);
|
||||
static void event_w(CPT_Event, void *data);
|
||||
static void event_t(CPT_Event, void *data);
|
||||
static void event_b(CPT_Event, void *data);
|
||||
static void event_l(CPT_Event, void *data);
|
||||
static void event_S(CPT_Event, void *data);
|
||||
|
||||
|
||||
private:
|
||||
bool _is_open;
|
||||
bool _made_default_pipe;
|
||||
|
||||
string _window_title;
|
||||
|
||||
PT(GraphicsPipe) _default_pipe;
|
||||
GraphicsEngine _engine;
|
||||
|
||||
qpNodePath _data_root;
|
||||
EventHandler _event_handler;
|
||||
|
||||
typedef pvector<WindowFramework *> Windows;
|
||||
Windows _windows;
|
||||
|
||||
// For counting frame rate.
|
||||
double _start_time;
|
||||
int _frame_count;
|
||||
|
||||
bool _wireframe_enabled;
|
||||
bool _texture_enabled;
|
||||
bool _two_sided_enabled;
|
||||
bool _lighting_enabled;
|
||||
|
||||
bool _default_keys_enabled;
|
||||
|
||||
bool _exit_flag;
|
||||
};
|
||||
|
||||
#include "pandaFramework.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Filename: windowFramework.I
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_panda_framework
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the associated PandaFramework
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PandaFramework *WindowFramework::
|
||||
get_panda_framework() const {
|
||||
return _panda_framework;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_graphics_window
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the underlying GraphicsWindow
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsWindow *WindowFramework::
|
||||
get_graphics_window() const {
|
||||
return _window;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_num_cameras
|
||||
// Access: Public
|
||||
// Description: Returns the number of 3-d cameras associated with the
|
||||
// window. A window usually has only one camera, but it
|
||||
// may have multiple cameras if there are multiple
|
||||
// display regions within the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int WindowFramework::
|
||||
get_num_cameras() const {
|
||||
return _cameras.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_camera
|
||||
// Access: Public
|
||||
// Description: Returns the nth camera associated with the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpCamera *WindowFramework::
|
||||
get_camera(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_cameras.size(), NULL);
|
||||
return _cameras[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_wireframe
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the wireframe flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowFramework::
|
||||
get_wireframe() const {
|
||||
return _wireframe_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_texture
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the texture flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowFramework::
|
||||
get_texture() const {
|
||||
return _texture_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_two_sided
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the two_sided flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowFramework::
|
||||
get_two_sided() const {
|
||||
return _two_sided_enabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_lighting
|
||||
// Access: Public
|
||||
// Description: Returns the current state of the lighting flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowFramework::
|
||||
get_lighting() const {
|
||||
return _lighting_enabled;
|
||||
}
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
// Filename: windowFramework.cxx
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "windowFramework.h"
|
||||
#include "pandaFramework.h"
|
||||
#include "mouseAndKeyboard.h"
|
||||
#include "qpbuttonThrower.h"
|
||||
#include "qptrackball.h"
|
||||
#include "qptransform2sg.h"
|
||||
#include "dSearchPath.h"
|
||||
#include "filename.h"
|
||||
#include "loader.h"
|
||||
#include "keyboardButton.h"
|
||||
#include "geomTri.h"
|
||||
#include "texturePool.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "perspectiveLens.h"
|
||||
#include "auto_bind.h"
|
||||
#include "ambientLight.h"
|
||||
#include "directionalLight.h"
|
||||
#include "lightAttrib.h"
|
||||
|
||||
// This number is chosen arbitrarily to override any settings in model
|
||||
// files.
|
||||
static const int override_priority = 100;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
WindowFramework::
|
||||
WindowFramework(PandaFramework *panda_framework) :
|
||||
_panda_framework(panda_framework)
|
||||
{
|
||||
_alight = (AmbientLight *)NULL;
|
||||
_dlight = (DirectionalLight *)NULL;
|
||||
_got_keyboard = false;
|
||||
_got_trackball = false;
|
||||
_got_lights = false;
|
||||
_wireframe_enabled = false;
|
||||
_texture_enabled = true;
|
||||
_two_sided_enabled = false;
|
||||
_lighting_enabled = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::Destructor
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
WindowFramework::
|
||||
~WindowFramework() {
|
||||
close_window();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::open_window
|
||||
// Access: Protected
|
||||
// Description: Opens the actual window. This is normally called
|
||||
// only from PandaFramework::open_window().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow *WindowFramework::
|
||||
open_window(const GraphicsWindow::Properties &props, GraphicsPipe *pipe) {
|
||||
nassertr(_window == (GraphicsWindow *)NULL, _window);
|
||||
|
||||
_window = pipe->make_window(props);
|
||||
|
||||
// Set up a 3-d camera for the window by default.
|
||||
make_camera();
|
||||
return _window;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::close_window
|
||||
// Access: Protected
|
||||
// Description: Closes the window. This is normally called
|
||||
// from PandaFramework::close_window().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
close_window() {
|
||||
_window.clear();
|
||||
_camera_group.remove_node();
|
||||
_render.remove_node();
|
||||
_render_2d.remove_node();
|
||||
_mouse.remove_node();
|
||||
|
||||
_alight = (AmbientLight *)NULL;
|
||||
_dlight = (DirectionalLight *)NULL;
|
||||
_got_keyboard = false;
|
||||
_got_trackball = false;
|
||||
_got_lights = false;
|
||||
|
||||
_wireframe_enabled = false;
|
||||
_texture_enabled = true;
|
||||
_two_sided_enabled = false;
|
||||
_lighting_enabled = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_camera_group
|
||||
// Access: Public
|
||||
// Description: Returns the node above the collection of 3-d cameras
|
||||
// in the scene graph. This node may be moved around to
|
||||
// represent the viewpoint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const qpNodePath &WindowFramework::
|
||||
get_camera_group() {
|
||||
if (_camera_group.is_empty()) {
|
||||
_camera_group = get_render().attach_new_node("camera_group");
|
||||
}
|
||||
return _camera_group;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_render
|
||||
// Access: Public
|
||||
// Description: Returns the root of the 3-d scene graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const qpNodePath &WindowFramework::
|
||||
get_render() {
|
||||
if (_render.is_empty()) {
|
||||
_render = qpNodePath("render");
|
||||
|
||||
// This is maybe here temporarily, and maybe not.
|
||||
_render.set_two_sided(0);
|
||||
}
|
||||
return _render;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_render_2d
|
||||
// Access: Public
|
||||
// Description: Returns the root of the 2-d scene graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const qpNodePath &WindowFramework::
|
||||
get_render_2d() {
|
||||
if (_render_2d.is_empty()) {
|
||||
_render_2d = qpNodePath("render_2d");
|
||||
}
|
||||
return _render_2d;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::get_mouse
|
||||
// Access: Public
|
||||
// Description: Returns the node in the data graph corresponding to
|
||||
// the mouse associated with this window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const qpNodePath &WindowFramework::
|
||||
get_mouse() {
|
||||
if (_mouse.is_empty()) {
|
||||
qpNodePath data_root = _panda_framework->get_data_root();
|
||||
qpMouseAndKeyboard *mouse_node =
|
||||
new qpMouseAndKeyboard(_window, 0, "mouse");
|
||||
_mouse = data_root.attach_new_node(mouse_node);
|
||||
}
|
||||
return _mouse;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::enable_keyboard
|
||||
// Access: Public
|
||||
// Description: Creates a ButtonThrower to listen to button presses
|
||||
// and throw them as events.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
enable_keyboard() {
|
||||
if (_got_keyboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath mouse = get_mouse();
|
||||
|
||||
PT(qpButtonThrower) bt = new qpButtonThrower("kb-events");
|
||||
ModifierButtons mods;
|
||||
mods.add_button(KeyboardButton::shift());
|
||||
mods.add_button(KeyboardButton::control());
|
||||
mods.add_button(KeyboardButton::alt());
|
||||
bt->set_modifier_buttons(mods);
|
||||
mouse.attach_new_node(bt);
|
||||
|
||||
_got_keyboard = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::setup_trackball
|
||||
// Access: Public
|
||||
// Description: Sets up the mouse to trackball around the camera.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
setup_trackball() {
|
||||
if (_got_trackball) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath mouse = get_mouse();
|
||||
qpNodePath camera = get_camera_group();
|
||||
|
||||
PT(qpTrackball) trackball = new qpTrackball("trackball");
|
||||
trackball->set_pos(LVector3f::forward() * 50.0);
|
||||
mouse.attach_new_node(trackball);
|
||||
|
||||
PT(qpTransform2SG) tball2cam = new qpTransform2SG("tball2cam");
|
||||
tball2cam->set_node(camera.node());
|
||||
trackball->add_child(tball2cam);
|
||||
|
||||
_got_trackball = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::load_models
|
||||
// Access: Public
|
||||
// Description: Loads up all the model files listed in the indicated
|
||||
// argument list. If first_arg is supplied, it is the
|
||||
// first argument in the list to consider.
|
||||
//
|
||||
// Returns true if all models loaded successfully, or
|
||||
// false if at least one of them had an error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool WindowFramework::
|
||||
load_models(const qpNodePath &parent, int argc, char *argv[], int first_arg) {
|
||||
pvector<Filename> files;
|
||||
|
||||
for (int i = first_arg; i < argc && argv[i] != (char *)NULL; i++) {
|
||||
files.push_back(Filename::from_os_specific(argv[i]));
|
||||
}
|
||||
|
||||
return load_models(parent, files);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::load_models
|
||||
// Access: Public
|
||||
// Description: Loads up all the model files listed in the indicated
|
||||
// argument list.
|
||||
//
|
||||
// Returns true if all models loaded successfully, or
|
||||
// false if at least one of them had an error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool WindowFramework::
|
||||
load_models(const qpNodePath &parent, const pvector<Filename> &files) {
|
||||
bool all_ok = true;
|
||||
|
||||
qpNodePath render = get_render();
|
||||
|
||||
pvector<Filename>::const_iterator fi;
|
||||
for (fi = files.begin(); fi != files.end(); ++fi) {
|
||||
const Filename &filename = (*fi);
|
||||
qpNodePath model = load_model(parent, filename);
|
||||
if (model.is_empty()) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::load_model
|
||||
// Access: Public
|
||||
// Description: Loads up the indicated model and returns the new
|
||||
// NodePath, or the empty NodePath if the model could
|
||||
// not be loaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpNodePath WindowFramework::
|
||||
load_model(const qpNodePath &parent, Filename filename) {
|
||||
nout << "Loading " << filename << "\n";
|
||||
|
||||
// First, we always try to resolve a filename from the current
|
||||
// directory. This means a local filename will always be found
|
||||
// before the model path is searched.
|
||||
DSearchPath local_path(".");
|
||||
filename.resolve_filename(local_path);
|
||||
|
||||
Loader loader;
|
||||
PT(PandaNode) node = loader.qpload_sync(filename);
|
||||
if (node == (PandaNode *)NULL) {
|
||||
nout << "Unable to load " << filename << "\n";
|
||||
return qpNodePath::not_found();
|
||||
}
|
||||
|
||||
return parent.attach_new_node(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::load_default_model
|
||||
// Access: Public
|
||||
// Description: Loads our favorite blue triangle. This is intended
|
||||
// to provide some default geometry to have *something*
|
||||
// to look at for testing, when no other models are
|
||||
// provided.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpNodePath WindowFramework::
|
||||
load_default_model(const qpNodePath &parent) {
|
||||
PTA_Vertexf coords;
|
||||
PTA_TexCoordf uvs;
|
||||
PTA_Normalf norms;
|
||||
PTA_Colorf colors;
|
||||
PTA_ushort cindex;
|
||||
|
||||
coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0));
|
||||
coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0));
|
||||
coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0));
|
||||
uvs.push_back(TexCoordf(0.0, 0.0));
|
||||
uvs.push_back(TexCoordf(1.0, 0.0));
|
||||
uvs.push_back(TexCoordf(0.0, 1.0));
|
||||
norms.push_back(Normalf::back());
|
||||
colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0));
|
||||
cindex.push_back(0);
|
||||
cindex.push_back(0);
|
||||
cindex.push_back(0);
|
||||
|
||||
PT(GeomTri) geom = new GeomTri;
|
||||
geom->set_num_prims(1);
|
||||
geom->set_coords(coords);
|
||||
geom->set_texcoords(uvs, G_PER_VERTEX);
|
||||
geom->set_normals(norms, G_PER_PRIM);
|
||||
geom->set_colors(colors, G_PER_VERTEX, cindex);
|
||||
|
||||
CPT(RenderState) state = RenderState::make_empty();
|
||||
Texture *tex = TexturePool::load_texture("rock-floor.rgb");
|
||||
if (tex != (Texture *)NULL) {
|
||||
tex->set_minfilter(Texture::FT_linear);
|
||||
tex->set_magfilter(Texture::FT_linear);
|
||||
state = state->add_attrib(TextureAttrib::make(tex));
|
||||
}
|
||||
|
||||
qpGeomNode *geomnode = new qpGeomNode("tri");
|
||||
geomnode->add_geom(geom, state);
|
||||
|
||||
return parent.attach_new_node(geomnode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::loop_animations
|
||||
// Access: Public
|
||||
// Description: Looks for characters and their matching animation
|
||||
// files in the scene graph; binds and loops any
|
||||
// matching animations found.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
loop_animations() {
|
||||
// If we happened to load up both a character file and its matching
|
||||
// animation file, attempt to bind them together now and start the
|
||||
// animations looping.
|
||||
auto_bind(get_render().node(), _anim_controls, ~0);
|
||||
_anim_controls.loop_all(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::set_wireframe
|
||||
// Access: Public
|
||||
// Description: Forces wireframe state (true) or restores default
|
||||
// rendering (false).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
set_wireframe(bool enable) {
|
||||
if (enable == _wireframe_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath render = get_render();
|
||||
|
||||
if (enable) {
|
||||
render.set_render_mode_wireframe(override_priority);
|
||||
render.set_two_sided(true, override_priority);
|
||||
} else {
|
||||
render.clear_render_mode();
|
||||
if (!_two_sided_enabled) {
|
||||
render.clear_two_sided();
|
||||
}
|
||||
}
|
||||
|
||||
_wireframe_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::set_texture
|
||||
// Access: Public
|
||||
// Description: Forces textures off (false) or restores default
|
||||
// rendering (true).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
set_texture(bool enable) {
|
||||
if (enable == _texture_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath render = get_render();
|
||||
|
||||
if (!enable) {
|
||||
render.set_texture_off(override_priority);
|
||||
} else {
|
||||
render.clear_texture();
|
||||
}
|
||||
|
||||
_texture_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::set_two_sided
|
||||
// Access: Public
|
||||
// Description: Forces two-sided rendering (true) or restores default
|
||||
// rendering (false).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
set_two_sided(bool enable) {
|
||||
if (enable == _two_sided_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath render = get_render();
|
||||
|
||||
if (enable) {
|
||||
render.set_two_sided(true, override_priority);
|
||||
} else {
|
||||
if (!_wireframe_enabled) {
|
||||
render.clear_two_sided();
|
||||
}
|
||||
}
|
||||
|
||||
_two_sided_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::set_lighting
|
||||
// Access: Public
|
||||
// Description: Turns lighting on (true) or off (false).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
set_lighting(bool enable) {
|
||||
if (enable == _lighting_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath render = get_render();
|
||||
|
||||
if (enable) {
|
||||
if (!_got_lights) {
|
||||
setup_lights();
|
||||
}
|
||||
render.node()->set_attrib(LightAttrib::make(LightAttrib::O_add,
|
||||
_alight, _dlight));
|
||||
} else {
|
||||
render.node()->clear_attrib(LightAttrib::get_class_type());
|
||||
}
|
||||
|
||||
_lighting_enabled = enable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::make_camera
|
||||
// Access: Protected
|
||||
// Description: Makes a new 3-d camera for the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(qpCamera) WindowFramework::
|
||||
make_camera() {
|
||||
// Get the first channel on the window. This will be the only
|
||||
// channel on non-SGI hardware.
|
||||
PT(GraphicsChannel) channel = _window->get_channel(0);
|
||||
|
||||
// Make a layer on the channel to hold our display region.
|
||||
PT(GraphicsLayer) layer = channel->make_layer();
|
||||
|
||||
// And create a display region that covers the entire window.
|
||||
PT(DisplayRegion) dr = layer->make_display_region();
|
||||
|
||||
// Finally, we need a camera to associate with the display region.
|
||||
PT(qpCamera) camera = new qpCamera("camera");
|
||||
qpNodePath camera_np = get_camera_group().attach_new_node(camera);
|
||||
_cameras.push_back(camera);
|
||||
|
||||
PT(Lens) lens = new PerspectiveLens;
|
||||
lens->set_film_size(_window->get_width(), _window->get_height());
|
||||
camera->set_lens(lens);
|
||||
camera->set_scene(get_render());
|
||||
dr->set_qpcamera(camera_np);
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowFramework::setup_lights
|
||||
// Access: Protected
|
||||
// Description: Makes light nodes and attaches them to the camera for
|
||||
// viewing the scene.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void WindowFramework::
|
||||
setup_lights() {
|
||||
if (_got_lights) {
|
||||
return;
|
||||
}
|
||||
|
||||
qpNodePath camera_group = get_camera_group();
|
||||
qpNodePath light_group = camera_group.attach_new_node("lights");
|
||||
|
||||
_alight = new AmbientLight("ambient");
|
||||
_alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
_dlight = new DirectionalLight("directional");
|
||||
light_group.attach_new_node(_alight);
|
||||
light_group.attach_new_node(_dlight);
|
||||
|
||||
_got_lights = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Filename: windowFramework.h
|
||||
// Created by: drose (02Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WINDOWFRAMEWORK_H
|
||||
#define WINDOWFRAMEWORK_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "qpnodePath.h"
|
||||
#include "qpcamera.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "animControlCollection.h"
|
||||
#include "filename.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
|
||||
class PandaFramework;
|
||||
class AmbientLight;
|
||||
class DirectionalLight;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : WindowFramework
|
||||
// Description : This encapsulates the data that is normally
|
||||
// associated with a single window that we've opened.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_FRAMEWORK WindowFramework {
|
||||
protected:
|
||||
WindowFramework(PandaFramework *panda_framework);
|
||||
virtual ~WindowFramework();
|
||||
|
||||
GraphicsWindow *open_window(const GraphicsWindow::Properties &props,
|
||||
GraphicsPipe *pipe);
|
||||
void close_window();
|
||||
|
||||
public:
|
||||
INLINE PandaFramework *get_panda_framework() const;
|
||||
INLINE GraphicsWindow *get_graphics_window() const;
|
||||
const qpNodePath &get_camera_group();
|
||||
|
||||
INLINE int get_num_cameras() const;
|
||||
INLINE qpCamera *get_camera(int n) const;
|
||||
|
||||
const qpNodePath &get_render();
|
||||
const qpNodePath &get_render_2d();
|
||||
const qpNodePath &get_mouse();
|
||||
|
||||
void enable_keyboard();
|
||||
void setup_trackball();
|
||||
|
||||
bool load_models(const qpNodePath &parent,
|
||||
int argc, char *argv[], int first_arg = 1);
|
||||
bool load_models(const qpNodePath &parent,
|
||||
const pvector<Filename> &files);
|
||||
qpNodePath load_model(const qpNodePath &parent, Filename filename);
|
||||
qpNodePath load_default_model(const qpNodePath &parent);
|
||||
void loop_animations();
|
||||
|
||||
void set_wireframe(bool enable);
|
||||
void set_texture(bool enable);
|
||||
void set_two_sided(bool enable);
|
||||
void set_lighting(bool enable);
|
||||
|
||||
INLINE bool get_wireframe() const;
|
||||
INLINE bool get_texture() const;
|
||||
INLINE bool get_two_sided() const;
|
||||
INLINE bool get_lighting() const;
|
||||
|
||||
protected:
|
||||
PT(qpCamera) make_camera();
|
||||
void setup_lights();
|
||||
|
||||
private:
|
||||
PandaFramework *_panda_framework;
|
||||
PT(GraphicsWindow) _window;
|
||||
|
||||
qpNodePath _camera_group;
|
||||
typedef pvector< PT(qpCamera) > Cameras;
|
||||
Cameras _cameras;
|
||||
|
||||
qpNodePath _render;
|
||||
qpNodePath _render_2d;
|
||||
AnimControlCollection _anim_controls;
|
||||
|
||||
qpNodePath _mouse;
|
||||
|
||||
AmbientLight *_alight;
|
||||
DirectionalLight *_dlight;
|
||||
|
||||
bool _got_keyboard;
|
||||
bool _got_trackball;
|
||||
bool _got_lights;
|
||||
|
||||
bool _wireframe_enabled;
|
||||
bool _texture_enabled;
|
||||
bool _two_sided_enabled;
|
||||
bool _lighting_enabled;
|
||||
|
||||
friend class PandaFramework;
|
||||
};
|
||||
|
||||
#include "windowFramework.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -21,8 +21,37 @@
|
|||
|
||||
/* See dtoolsymbols.h for a rant on the purpose of this file. */
|
||||
|
||||
/* Note that the symbols declared in this file appear in alphabetical
|
||||
order. Also note that we must use C-style comments only here, not
|
||||
C++-style comments, since this file is occasionally included by a C
|
||||
file. */
|
||||
|
||||
#if defined(WIN32_VC) && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
|
||||
|
||||
#ifdef BUILDING_FRAMEWORK
|
||||
#define EXPCL_FRAMEWORK __declspec(dllexport)
|
||||
#define EXPTP_FRAMEWORK
|
||||
#else
|
||||
#define EXPCL_FRAMEWORK __declspec(dllimport)
|
||||
#define EXPTP_FRAMEWORK extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_LINUX_AUDIO
|
||||
#define EXPCL_LINUX_AUDIO __declspec(dllexport)
|
||||
#define EXPTP_LINUX_AUDIO
|
||||
#else
|
||||
#define EXPCL_LINUX_AUDIO __declspec(dllimport)
|
||||
#define EXPTP_LINUX_AUDIO extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_MILES_AUDIO
|
||||
#define EXPCL_MILES_AUDIO __declspec(dllexport)
|
||||
#define EXPTP_MILES_AUDIO
|
||||
#else
|
||||
#define EXPCL_MILES_AUDIO __declspec(dllimport)
|
||||
#define EXPTP_MILES_AUDIO extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDA
|
||||
#define EXPCL_PANDA __declspec(dllexport)
|
||||
#define EXPTP_PANDA
|
||||
|
|
@ -31,6 +60,14 @@
|
|||
#define EXPTP_PANDA extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDACR
|
||||
#define EXPCL_PANDACR __declspec(dllexport)
|
||||
#define EXPTP_PANDACR
|
||||
#else
|
||||
#define EXPCL_PANDACR __declspec(dllimport)
|
||||
#define EXPTP_PANDACR extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDADX
|
||||
#define EXPCL_PANDADX __declspec(dllexport)
|
||||
#define EXPTP_PANDADX
|
||||
|
|
@ -71,14 +108,6 @@
|
|||
#define EXPTP_PANDAGL extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDACR
|
||||
#define EXPCL_PANDACR __declspec(dllexport)
|
||||
#define EXPTP_PANDACR
|
||||
#else
|
||||
#define EXPCL_PANDACR __declspec(dllimport)
|
||||
#define EXPTP_PANDACR extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDAGLUT
|
||||
#define EXPCL_PANDAGLUT __declspec(dllexport)
|
||||
#define EXPTP_PANDAGLUT
|
||||
|
|
@ -111,27 +140,23 @@
|
|||
#define EXPTP_SHADER extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_MILES_AUDIO
|
||||
#define EXPCL_MILES_AUDIO __declspec(dllexport)
|
||||
#define EXPTP_MILES_AUDIO
|
||||
#else
|
||||
#define EXPCL_MILES_AUDIO __declspec(dllimport)
|
||||
#define EXPTP_MILES_AUDIO extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_LINUX_AUDIO
|
||||
#define EXPCL_LINUX_AUDIO __declspec(dllexport)
|
||||
#define EXPTP_LINUX_AUDIO
|
||||
#else
|
||||
#define EXPCL_LINUX_AUDIO __declspec(dllimport)
|
||||
#define EXPTP_LINUX_AUDIO extern
|
||||
#endif
|
||||
|
||||
#else /* !WIN32_VC */
|
||||
|
||||
#define EXPCL_FRAMEWORK
|
||||
#define EXPTP_FRAMEWORK
|
||||
|
||||
#define EXPCL_LINUX_AUDIO
|
||||
#define EXPTP_LINUX_AUDIO
|
||||
|
||||
#define EXPCL_MILES_AUDIO
|
||||
#define EXPTP_MILES_AUDIO
|
||||
|
||||
#define EXPCL_PANDA
|
||||
#define EXPTP_PANDA
|
||||
|
||||
#define EXPCL_PANDACR
|
||||
#define EXPTP_PANDACR
|
||||
|
||||
#define EXPCL_PANDADX
|
||||
#define EXPTP_PANDADX
|
||||
|
||||
|
|
@ -147,9 +172,6 @@
|
|||
#define EXPCL_PANDAGL
|
||||
#define EXPTP_PANDAGL
|
||||
|
||||
#define EXPCL_PANDACR
|
||||
#define EXPTP_PANDACR
|
||||
|
||||
#define EXPCL_PANDAGLUT
|
||||
#define EXPTP_PANDAGLUT
|
||||
|
||||
|
|
@ -162,15 +184,6 @@
|
|||
#define EXPCL_SHADER
|
||||
#define EXPTP_SHADER
|
||||
|
||||
#define EXPCL_MILES_AUDIO
|
||||
#define EXPTP_MILES_AUDIO
|
||||
|
||||
#define EXPCL_LINUX_AUDIO
|
||||
#define EXPTP_LINUX_AUDIO
|
||||
|
||||
#define EXPCL_FRAMEWORK
|
||||
#define EXPTP_FRAMEWORK
|
||||
|
||||
#endif /* WIN32_VC */
|
||||
|
||||
#if defined(WIN32_VC) && !defined(CPPPARSER)
|
||||
|
|
|
|||
|
|
@ -10,21 +10,12 @@
|
|||
#if $[LINK_ALL_STATIC]
|
||||
// If we're statically linking, we need to explicitly link with
|
||||
// at least one graphics renderer.
|
||||
#define LOCAL_LIBS pandacr pandagl pandadx $[LOCAL_LIBS]
|
||||
#define LOCAL_LIBS pandagl pandadx $[LOCAL_LIBS]
|
||||
|
||||
// And we might like to have the egg loader available.
|
||||
#define LOCAL_LIBS pandaegg $[LOCAL_LIBS]
|
||||
#endif
|
||||
|
||||
#define UNIX_SYS_LIBS m
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET demo
|
||||
|
||||
#define SOURCES \
|
||||
demo.cxx
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET pview
|
||||
|
|
@ -34,138 +25,8 @@
|
|||
#end bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET open_window
|
||||
#define TARGET pgrid
|
||||
|
||||
#define SOURCES \
|
||||
open_window.cxx
|
||||
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] pandacr pandagl pandadx
|
||||
#end test_bin_target
|
||||
|
||||
#if $[HAVE_DX]
|
||||
#begin test_bin_target
|
||||
#define TARGET demo_multimon
|
||||
|
||||
#define SOURCES \
|
||||
demo.cxx
|
||||
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] pandadx framework_multimon
|
||||
#end test_bin_target
|
||||
#endif
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET downloader
|
||||
|
||||
#define SOURCES \
|
||||
downloader_test.cxx
|
||||
|
||||
#define USE_ZLIB yes
|
||||
#define TARGET_IF_ZLIB yes
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET herc
|
||||
|
||||
#define SOURCES \
|
||||
herc.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET loader
|
||||
|
||||
#define SOURCES \
|
||||
loader_test.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET lod
|
||||
|
||||
#define SOURCES \
|
||||
lod_test.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET min_herc
|
||||
|
||||
#define SOURCES \
|
||||
min_herc.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET min_shader
|
||||
|
||||
#define SOURCES \
|
||||
min_shader.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET panda
|
||||
|
||||
#define SOURCES \
|
||||
panda.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET shader
|
||||
|
||||
#define SOURCES \
|
||||
shader_test.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_eggWrite
|
||||
|
||||
#define SOURCES \
|
||||
test_eggWrite.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_particles
|
||||
|
||||
#define SOURCES \
|
||||
test_particles.cxx
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] physics particlesystem
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_sprite_particles
|
||||
|
||||
#define SOURCES \
|
||||
test_sprite_particles.cxx
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] physics particlesystem
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_recparticles
|
||||
|
||||
#define SOURCES \
|
||||
test_recparticles.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET text
|
||||
|
||||
#define SOURCES \
|
||||
text_test.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET vrpn_demo
|
||||
|
||||
#define SOURCES \
|
||||
vrpn_demo.cxx
|
||||
|
||||
pgrid.cxx
|
||||
#end test_bin_target
|
||||
|
|
|
|||
|
|
@ -0,0 +1,429 @@
|
|||
// Filename: pgrid.cxx
|
||||
// Created by: drose (03Apr02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaFramework.h"
|
||||
#include "pandaNode.h"
|
||||
#include "transformState.h"
|
||||
#include "clockObject.h"
|
||||
#include "string_utils.h"
|
||||
#include "pvector.h"
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
|
||||
#define RANDFRAC (rand()/(float)(RAND_MAX))
|
||||
|
||||
class GriddedFilename {
|
||||
public:
|
||||
Filename _filename;
|
||||
int _count;
|
||||
qpNodePath _model;
|
||||
};
|
||||
typedef pvector<GriddedFilename> GriddedFilenames;
|
||||
|
||||
typedef struct {
|
||||
// for rot moving
|
||||
float xcenter,ycenter;
|
||||
float xoffset,yoffset;
|
||||
float ang1,ang1_vel;
|
||||
float ang2,ang2_vel;
|
||||
|
||||
float radius;
|
||||
|
||||
// for moving
|
||||
float xstart,ystart;
|
||||
float xend,yend;
|
||||
float xdel,ydel,timedel;
|
||||
double starttime,endtime;
|
||||
double vel;
|
||||
LMatrix4f rotmat;
|
||||
|
||||
PandaNode *node;
|
||||
} gridded_file_info;
|
||||
|
||||
typedef pvector<gridded_file_info> GriddedInfoArray;
|
||||
|
||||
typedef enum {None,Rotation,LinearMotion} GriddedMotionType;
|
||||
|
||||
#define GRIDCELLSIZE 5.0
|
||||
static int gridwidth; // cells/side
|
||||
|
||||
#define MIN_WANDERAREA_DIMENSION 120.0
|
||||
|
||||
static float grid_pos_offset; // origin of grid
|
||||
static float wander_area_pos_offset;
|
||||
|
||||
static GriddedMotionType gridmotiontype = None;
|
||||
|
||||
|
||||
// making these fns to get around ridiculous VC++ matrix inlining bugs at Opt2
|
||||
static void
|
||||
move_gridded_stuff(GriddedMotionType gridmotiontype,
|
||||
gridded_file_info *InfoArr, int size) {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
|
||||
LMatrix4f tmat1,tmat2,xfm_mat;
|
||||
|
||||
for(int i = 0; i < size; i++) {
|
||||
double time_delta = (now-InfoArr[i].starttime);
|
||||
#define DO_FP_MODULUS(VAL,MAXVAL) \
|
||||
{if(VAL > MAXVAL) {int idivresult = (int)(VAL / (float)MAXVAL); VAL=VAL-idivresult*MAXVAL;} else \
|
||||
if(VAL < -MAXVAL) {int idivresult = (int)(VAL / (float)MAXVAL); VAL=VAL+idivresult*MAXVAL;}}
|
||||
|
||||
// probably should use panda lerps for this stuff, but I dont understand how
|
||||
|
||||
if(gridmotiontype==Rotation) {
|
||||
|
||||
InfoArr[i].ang1=time_delta*InfoArr[i].ang1_vel;
|
||||
DO_FP_MODULUS(InfoArr[i].ang1,360.0);
|
||||
InfoArr[i].ang2=time_delta*InfoArr[i].ang2_vel;
|
||||
DO_FP_MODULUS(InfoArr[i].ang2,360.0);
|
||||
|
||||
// xforms happen left to right
|
||||
LVector2f new_center = LVector2f(InfoArr[i].radius,0.0) *
|
||||
LMatrix3f::rotate_mat(InfoArr[i].ang1);
|
||||
|
||||
LVector3f translate_vec(InfoArr[i].xcenter+new_center._v.v._0,
|
||||
InfoArr[i].ycenter+new_center._v.v._1,
|
||||
0.0);
|
||||
|
||||
const LVector3f rotation_axis(0.0, 0.0, 1.0);
|
||||
|
||||
tmat1 = LMatrix4f::rotate_mat_normaxis(InfoArr[i].ang2,rotation_axis);
|
||||
tmat2 = LMatrix4f::translate_mat(translate_vec);
|
||||
xfm_mat = tmat1 * tmat2;
|
||||
} else {
|
||||
|
||||
float xpos,ypos;
|
||||
|
||||
if(now>InfoArr[i].endtime) {
|
||||
InfoArr[i].starttime = now;
|
||||
|
||||
xpos = InfoArr[i].xstart = InfoArr[i].xend;
|
||||
ypos = InfoArr[i].ystart = InfoArr[i].yend;
|
||||
|
||||
InfoArr[i].xend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
|
||||
InfoArr[i].yend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
|
||||
|
||||
float xdel = InfoArr[i].xdel = InfoArr[i].xend-InfoArr[i].xstart;
|
||||
float ydel = InfoArr[i].ydel = InfoArr[i].yend-InfoArr[i].ystart;
|
||||
|
||||
InfoArr[i].endtime = now + csqrt(xdel*xdel+ydel*ydel)/InfoArr[i].vel;
|
||||
InfoArr[i].timedel = InfoArr[i].endtime - InfoArr[i].starttime;
|
||||
|
||||
const LVector3f rotate_axis(0.0, 0.0, 1.0);
|
||||
|
||||
float ang = rad_2_deg(atan2(-xdel,ydel));
|
||||
|
||||
InfoArr[i].rotmat= LMatrix4f::rotate_mat_normaxis(ang,rotate_axis);
|
||||
} else {
|
||||
float timefrac= time_delta/InfoArr[i].timedel;
|
||||
|
||||
xpos = InfoArr[i].xdel*timefrac+InfoArr[i].xstart;
|
||||
ypos = InfoArr[i].ydel*timefrac+InfoArr[i].ystart;
|
||||
}
|
||||
|
||||
LVector3f translate_vec(xpos, ypos, 0.0);
|
||||
LMatrix4f tmat2 = LMatrix4f::translate_mat(translate_vec);
|
||||
|
||||
xfm_mat = InfoArr[i].rotmat * tmat2;
|
||||
}
|
||||
InfoArr[i].node->set_transform(TransformState::make_mat(xfm_mat));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
get_command_line_opts(int &argc, char **&argv) {
|
||||
// Use getopt() to decode the optional command-line parameters.
|
||||
// extern char *optarg;
|
||||
extern int optind;
|
||||
const char *options = "rm";
|
||||
int flag = getopt(argc, argv, options);
|
||||
while (flag != EOF) {
|
||||
switch (flag) {
|
||||
case 'r':
|
||||
gridmotiontype = Rotation;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
gridmotiontype = LinearMotion;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
nout << "Invalid parameter.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
flag = getopt(argc, argv, options);
|
||||
}
|
||||
|
||||
argv += (optind - 1);
|
||||
argc -= (optind - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
get_command_line_filenames(int argc, char *argv[],
|
||||
pvector<Filename> &static_filenames,
|
||||
GriddedFilenames &gridded_filenames) {
|
||||
for (int i = 1; i < argc && argv[i] != (char *)NULL; i++) {
|
||||
const string &arg = argv[i];
|
||||
size_t comma = arg.find(',');
|
||||
if (comma == string::npos) {
|
||||
// No comma in the filename, so it must be an ordinary static file.
|
||||
static_filenames.push_back(Filename::from_os_specific(arg));
|
||||
|
||||
} else {
|
||||
// A comma in the filename indicates a gridded file. The syntax
|
||||
// is filename,count where count represents the number of times
|
||||
// the file is repeated.
|
||||
string name = arg.substr(0, comma);
|
||||
string count_str = arg.substr(comma + 1);
|
||||
int count;
|
||||
if (!string_to_int(count_str, count)) {
|
||||
nout << "Ignoring invalid number: " << count_str << "\n";
|
||||
count = 1;
|
||||
} else if (count <= 0) {
|
||||
nout << "Ignoring inappropriate number: " << count << "\n";
|
||||
count = 1;
|
||||
}
|
||||
|
||||
GriddedFilename gf;
|
||||
gf._filename = Filename::from_os_specific(name);
|
||||
gf._count = count;
|
||||
gridded_filenames.push_back(gf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
load_gridded_models(WindowFramework *window,
|
||||
GriddedFilenames &filenames,
|
||||
GriddedInfoArray &info_arr) {
|
||||
// Load up all the files indicated in the list of gridded filenames
|
||||
// and store them in the given vector.
|
||||
|
||||
// First, load up each model from disk once, and store them all
|
||||
// separate from the scene graph. Also count up the total number of
|
||||
// models we'll be putting in the grid.
|
||||
int grid_count = 0;
|
||||
qpNodePath models("models");
|
||||
GriddedFilenames::iterator fi;
|
||||
for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
|
||||
GriddedFilename &gf = (*fi);
|
||||
gf._model = window->load_model(models, gf._filename);
|
||||
if (!gf._model.is_empty()) {
|
||||
grid_count += gf._count;
|
||||
}
|
||||
}
|
||||
|
||||
info_arr.clear();
|
||||
info_arr.reserve(grid_count);
|
||||
|
||||
// Compute the integer square root of grid_count, so that we put our
|
||||
// models in a nice square grid.
|
||||
|
||||
gridwidth=1;
|
||||
while(gridwidth*gridwidth < grid_count) {
|
||||
gridwidth++;
|
||||
}
|
||||
|
||||
grid_pos_offset = -gridwidth*GRIDCELLSIZE/2.0;
|
||||
wander_area_pos_offset = -max(fabs(grid_pos_offset),MIN_WANDERAREA_DIMENSION/2.0);
|
||||
|
||||
// Now walk through the list again, copying models into the scene
|
||||
// graph as we go.
|
||||
|
||||
float xpos = grid_pos_offset;
|
||||
float ypos = grid_pos_offset;
|
||||
|
||||
srand( (unsigned)time( NULL ) );
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
|
||||
int model_count = 0;
|
||||
int passnum = 0;
|
||||
bool loaded_any;
|
||||
|
||||
qpNodePath render = window->get_render();
|
||||
do {
|
||||
loaded_any = false;
|
||||
|
||||
for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
|
||||
const GriddedFilename &gf = (*fi);
|
||||
if (!gf._model.is_empty() && gf._count > passnum) {
|
||||
loaded_any = true;
|
||||
// Copy this model into the scene graph, and assign it a
|
||||
// position on the grid.
|
||||
|
||||
string model_name = format_string(++model_count);
|
||||
qpNodePath model = render.attach_new_node(model_name);
|
||||
gf._model.copy_to(model);
|
||||
|
||||
gridded_file_info info;
|
||||
info.node = model.node();
|
||||
|
||||
LMatrix4f xfm_mat,tmat1,tmat2;
|
||||
|
||||
if(gridmotiontype==Rotation) {
|
||||
|
||||
#define MIN_REVOLUTION_ANGVEL 30
|
||||
#define MAX_REVOLUTION_ANGVEL 60
|
||||
|
||||
#define MIN_ROTATION_ANGVEL 30
|
||||
#define MAX_ROTATION_ANGVEL 600
|
||||
|
||||
#define MAX_RADIUS 4.0*GRIDCELLSIZE
|
||||
#define MIN_RADIUS 0.1*GRIDCELLSIZE
|
||||
|
||||
info.starttime = now;
|
||||
|
||||
info.xcenter=xpos;
|
||||
info.ycenter=ypos;
|
||||
info.ang1=RANDFRAC * 360.0;
|
||||
info.ang1_vel=((MAX_REVOLUTION_ANGVEL-MIN_REVOLUTION_ANGVEL) * RANDFRAC) + MIN_REVOLUTION_ANGVEL;
|
||||
|
||||
info.ang2=RANDFRAC * 360.0;
|
||||
info.ang2_vel=((MAX_ROTATION_ANGVEL-MIN_ROTATION_ANGVEL) * RANDFRAC) + MIN_ROTATION_ANGVEL;
|
||||
|
||||
info.radius = (RANDFRAC * (MAX_RADIUS-MIN_RADIUS)) + MIN_RADIUS;
|
||||
|
||||
if(RANDFRAC>0.5) {
|
||||
info.ang1_vel=-info.ang1_vel;
|
||||
}
|
||||
|
||||
if(RANDFRAC>0.5) {
|
||||
info.ang2_vel=-info.ang2_vel;
|
||||
}
|
||||
|
||||
// xforms happen left to right
|
||||
LVector2f new_center = LVector2f(info.radius,0.0) *
|
||||
LMatrix3f::rotate_mat(info.ang1);
|
||||
|
||||
const LVector3f rotate_axis(0.0, 0.0, 1.0);
|
||||
|
||||
LVector3f translate_vec(xpos+new_center._v.v._0,
|
||||
ypos+new_center._v.v._1,
|
||||
0.0);
|
||||
|
||||
LMatrix4f::rotate_mat_normaxis(info.ang2,rotate_axis,tmat1);
|
||||
tmat2 = LMatrix4f::translate_mat(translate_vec);
|
||||
xfm_mat = tmat1 * tmat2;
|
||||
} else if(gridmotiontype==LinearMotion) {
|
||||
|
||||
#define MIN_VEL 2.0
|
||||
#define MAX_VEL (fabs(wander_area_pos_offset))
|
||||
|
||||
info.vel=((MAX_VEL-MIN_VEL) * RANDFRAC) + MIN_VEL;
|
||||
|
||||
info.xstart=xpos;
|
||||
info.ystart=ypos;
|
||||
|
||||
info.xend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
|
||||
info.yend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
|
||||
|
||||
info.starttime = now;
|
||||
|
||||
float xdel = info.xdel = info.xend-info.xstart;
|
||||
float ydel = info.ydel = info.yend-info.ystart;
|
||||
|
||||
info.endtime = csqrt(xdel*xdel+ydel*ydel)/info.vel;
|
||||
|
||||
info.timedel = info.endtime - info.starttime;
|
||||
|
||||
const LVector3f rotate_axis(0.0, 0.0, 1.0);
|
||||
float ang = rad_2_deg(atan2(-xdel,ydel));
|
||||
|
||||
LMatrix4f::rotate_mat_normaxis(ang,rotate_axis,info.rotmat);
|
||||
|
||||
LVector3f translate_vec(xpos, ypos, 0.0);
|
||||
LMatrix4f tmat2 = LMatrix4f::translate_mat(translate_vec);
|
||||
|
||||
xfm_mat = info.rotmat * tmat2;
|
||||
} else {
|
||||
LVector3f translate_vec(xpos, ypos, 0.0);
|
||||
xfm_mat = LMatrix4f::translate_mat(translate_vec);
|
||||
}
|
||||
|
||||
info.node->set_transform(TransformState::make_mat(xfm_mat));
|
||||
|
||||
info_arr.push_back(info);
|
||||
|
||||
if((model_count % gridwidth) == 0) {
|
||||
xpos= -gridwidth*GRIDCELLSIZE/2.0;
|
||||
ypos+=GRIDCELLSIZE;
|
||||
} else {
|
||||
xpos+=GRIDCELLSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
passnum++;
|
||||
} while (loaded_any);
|
||||
|
||||
// Finally, remove the source models we loaded up. Not a real big deal.
|
||||
for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
|
||||
GriddedFilename &gf = (*fi);
|
||||
if (!gf._model.is_empty()) {
|
||||
gf._model.remove_node();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
PandaFramework framework;
|
||||
vector_string args;
|
||||
framework.open_framework(argc, argv);
|
||||
framework.set_window_title("Gridded Object Viewer");
|
||||
|
||||
if (!get_command_line_opts(argc, argv)) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Extract the remaining arguments into two lists of files: those
|
||||
// with a grid parameter, and those without.
|
||||
pvector<Filename> static_filenames;
|
||||
GriddedFilenames gridded_filenames;
|
||||
get_command_line_filenames(argc, argv, static_filenames, gridded_filenames);
|
||||
|
||||
WindowFramework *window = framework.open_window();
|
||||
if (window != (WindowFramework *)NULL) {
|
||||
// We've successfully opened a window.
|
||||
|
||||
window->enable_keyboard();
|
||||
window->setup_trackball();
|
||||
window->load_models(window->get_render(), static_filenames);
|
||||
|
||||
GriddedInfoArray info_arr;
|
||||
load_gridded_models(window, gridded_filenames, info_arr);
|
||||
|
||||
window->loop_animations();
|
||||
|
||||
framework.enable_default_keys();
|
||||
|
||||
while (framework.do_frame()) {
|
||||
if (!info_arr.empty() && gridmotiontype) {
|
||||
move_gridded_stuff(gridmotiontype, &info_arr[0], info_arr.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
framework.report_frame_rate(nout);
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -16,453 +16,27 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsLayer.h"
|
||||
#include "graphicsEngine.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "interactiveGraphicsPipe.h"
|
||||
#include "displayRegion.h"
|
||||
#include "qpcamera.h"
|
||||
#include "perspectiveLens.h"
|
||||
#include "pandaNode.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "clockObject.h"
|
||||
#include "qpgeomNode.h"
|
||||
#include "geomTri.h"
|
||||
#include "texture.h"
|
||||
#include "texturePool.h"
|
||||
#include "dSearchPath.h"
|
||||
#include "loader.h"
|
||||
#include "auto_bind.h"
|
||||
#include "pStatClient.h"
|
||||
#include "notify.h"
|
||||
#include "qpnodePath.h"
|
||||
#include "cullBinManager.h"
|
||||
#include "mouseAndKeyboard.h"
|
||||
#include "qpbuttonThrower.h"
|
||||
#include "qptrackball.h"
|
||||
#include "qptransform2sg.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "keyboardButton.h"
|
||||
#include "event.h"
|
||||
#include "eventQueue.h"
|
||||
#include "eventHandler.h"
|
||||
#include "qpdataGraphTraverser.h"
|
||||
#include "lightAttrib.h"
|
||||
#include "ambientLight.h"
|
||||
#include "directionalLight.h"
|
||||
|
||||
// Use dconfig to read a few Configrc variables.
|
||||
Configure(config_pview);
|
||||
ConfigureFn(config_pview) {
|
||||
}
|
||||
|
||||
static const int win_width = config_pview.GetInt("win-width", 640);
|
||||
static const int win_height = config_pview.GetInt("win-height", 480);
|
||||
|
||||
// As long as this is true, the main loop will continue running.
|
||||
bool run_flag = true;
|
||||
|
||||
// These are referenced in both event_w() and in event_b().
|
||||
bool wireframe = false;
|
||||
bool two_sided = false;
|
||||
bool lighting = false;
|
||||
|
||||
|
||||
// These are used by report_frame_rate().
|
||||
double start_time = 0.0;
|
||||
int start_frame_count = 0;
|
||||
|
||||
// A priority number high enough to override any model file settings.
|
||||
static const int override_priority = 100;
|
||||
|
||||
// This is the main scene graph.
|
||||
qpNodePath render;
|
||||
|
||||
// And this is the camera node.
|
||||
qpNodePath camera_np;
|
||||
|
||||
void
|
||||
report_frame_rate() {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
double delta = now - start_time;
|
||||
|
||||
int frame_count = ClockObject::get_global_clock()->get_frame_count();
|
||||
int num_frames = frame_count - start_frame_count;
|
||||
if (num_frames > 0) {
|
||||
nout << endl << num_frames << " frames in " << delta << " seconds" << endl;
|
||||
double x = ((double)num_frames) / delta;
|
||||
nout << x << " fps average (" << 1000.0 / x << "ms)" << endl;
|
||||
|
||||
// Reset the frame rate counter for the next press of 'f'.
|
||||
start_time = now;
|
||||
start_frame_count = frame_count;
|
||||
}
|
||||
}
|
||||
|
||||
PT(GraphicsPipe)
|
||||
make_pipe() {
|
||||
// We use the GraphicsPipe factory to make us a renderable pipe
|
||||
// without knowing exactly what kind of pipes we have available. We
|
||||
// don't care, so long as we can render to it interactively.
|
||||
|
||||
// This depends on the shared library or libraries (DLL's to you
|
||||
// Windows folks) that have been loaded in at runtime from the
|
||||
// load-display Configrc variable.
|
||||
GraphicsPipe::resolve_modules();
|
||||
|
||||
nout << "Known pipe types:" << endl;
|
||||
GraphicsPipe::get_factory().write_types(nout, 2);
|
||||
|
||||
PT(GraphicsPipe) pipe;
|
||||
pipe = GraphicsPipe::get_factory().
|
||||
make_instance(InteractiveGraphicsPipe::get_class_type());
|
||||
|
||||
if (pipe == (GraphicsPipe*)0L) {
|
||||
nout << "No interactive pipe is available! Check your Configrc!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return pipe;
|
||||
}
|
||||
|
||||
PT(GraphicsWindow)
|
||||
make_window(GraphicsPipe *pipe, GraphicsEngine *engine) {
|
||||
// Now create a window on that pipe.
|
||||
GraphicsWindow::Properties window_prop;
|
||||
window_prop._xorg = 0;
|
||||
window_prop._yorg = 0;
|
||||
window_prop._xsize = win_width;
|
||||
window_prop._ysize = win_height;
|
||||
window_prop._title = "Panda Viewer";
|
||||
// window_prop._fullscreen = true;
|
||||
|
||||
PT(GraphicsWindow) window = pipe->make_window(window_prop);
|
||||
engine->add_window(window);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
PT(qpCamera)
|
||||
make_camera(GraphicsWindow *window) {
|
||||
// Get the first channel on the window. This will be the only
|
||||
// channel on non-SGI hardware.
|
||||
PT(GraphicsChannel) channel = window->get_channel(0);
|
||||
|
||||
// Make a layer on the channel to hold our display region.
|
||||
PT(GraphicsLayer) layer = channel->make_layer();
|
||||
|
||||
// And create a display region that covers the entire window.
|
||||
PT(DisplayRegion) dr = layer->make_display_region();
|
||||
|
||||
// Finally, we need a camera to associate with the display region.
|
||||
PT(qpCamera) camera = new qpCamera("camera");
|
||||
PT(Lens) lens = new PerspectiveLens;
|
||||
lens->set_film_size(win_width, win_height);
|
||||
camera->set_lens(lens);
|
||||
dr->set_qpcamera(qpNodePath(camera));
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
make_default_geometry(PandaNode *parent) {
|
||||
PTA_Vertexf coords;
|
||||
PTA_TexCoordf uvs;
|
||||
PTA_Normalf norms;
|
||||
PTA_Colorf colors;
|
||||
PTA_ushort cindex;
|
||||
|
||||
coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0));
|
||||
coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0));
|
||||
coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0));
|
||||
uvs.push_back(TexCoordf(0.0, 0.0));
|
||||
uvs.push_back(TexCoordf(1.0, 0.0));
|
||||
uvs.push_back(TexCoordf(0.0, 1.0));
|
||||
norms.push_back(Normalf::back());
|
||||
colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0));
|
||||
cindex.push_back(0);
|
||||
cindex.push_back(0);
|
||||
cindex.push_back(0);
|
||||
|
||||
PT(GeomTri) geom = new GeomTri;
|
||||
geom->set_num_prims(1);
|
||||
geom->set_coords(coords);
|
||||
geom->set_texcoords(uvs, G_PER_VERTEX);
|
||||
geom->set_normals(norms, G_PER_PRIM);
|
||||
geom->set_colors(colors, G_PER_VERTEX, cindex);
|
||||
|
||||
CPT(RenderState) state = RenderState::make_empty();
|
||||
Texture *tex = TexturePool::load_texture("rock-floor.rgb");
|
||||
if (tex != (Texture *)NULL) {
|
||||
tex->set_minfilter(Texture::FT_linear);
|
||||
tex->set_magfilter(Texture::FT_linear);
|
||||
state = state->add_attrib(TextureAttrib::make(tex));
|
||||
}
|
||||
|
||||
qpGeomNode *geomnode = new qpGeomNode("tri");
|
||||
parent->add_child(geomnode);
|
||||
geomnode->add_geom(geom, state);
|
||||
}
|
||||
|
||||
void
|
||||
get_models(PandaNode *parent, int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
// In the absence of any models on the command line, load up a
|
||||
// default triangle so we at least have something to look at.
|
||||
make_default_geometry(parent);
|
||||
|
||||
} else {
|
||||
Loader loader;
|
||||
DSearchPath local_path(".");
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
Filename filename = argv[i];
|
||||
|
||||
nout << "Loading " << filename << "\n";
|
||||
|
||||
// First, we always try to resolve a filename from the current
|
||||
// directory. This means a local filename will always be found
|
||||
// before the model path is searched.
|
||||
filename.resolve_filename(local_path);
|
||||
|
||||
PT(PandaNode) node = loader.qpload_sync(filename);
|
||||
if (node == (PandaNode *)NULL) {
|
||||
nout << "Unable to load " << filename << "\n";
|
||||
|
||||
} else {
|
||||
node->ls(nout, 0);
|
||||
parent->add_child(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PandaNode *
|
||||
setup_mouse(PandaNode *data_root, GraphicsWindow *window) {
|
||||
qpMouseAndKeyboard *mouse = new qpMouseAndKeyboard(window, 0, "mouse");
|
||||
data_root->add_child(mouse);
|
||||
|
||||
// Create a ButtonThrower to throw events from the keyboard.
|
||||
PT(qpButtonThrower) bt = new qpButtonThrower("kb-events");
|
||||
ModifierButtons mods;
|
||||
mods.add_button(KeyboardButton::shift());
|
||||
mods.add_button(KeyboardButton::control());
|
||||
mods.add_button(KeyboardButton::alt());
|
||||
bt->set_modifier_buttons(mods);
|
||||
mouse->add_child(bt);
|
||||
|
||||
return mouse;
|
||||
}
|
||||
|
||||
void
|
||||
setup_trackball(PandaNode *mouse, qpCamera *camera) {
|
||||
PT(qpTrackball) trackball = new qpTrackball("trackball");
|
||||
trackball->set_pos(LVector3f::forward() * 50.0);
|
||||
mouse->add_child(trackball);
|
||||
|
||||
PT(qpTransform2SG) tball2cam = new qpTransform2SG("tball2cam");
|
||||
tball2cam->set_node(camera);
|
||||
trackball->add_child(tball2cam);
|
||||
}
|
||||
|
||||
void
|
||||
event_esc(CPT_Event) {
|
||||
// The Escape or q key was pressed. Exit the application.
|
||||
run_flag = false;
|
||||
}
|
||||
|
||||
void
|
||||
event_f(CPT_Event) {
|
||||
// 'f' : report frame rate.
|
||||
report_frame_rate();
|
||||
}
|
||||
|
||||
void
|
||||
event_t(CPT_Event) {
|
||||
// 't' : toggle texture.
|
||||
static bool texture_off = false;
|
||||
|
||||
texture_off = !texture_off;
|
||||
if (texture_off) {
|
||||
nout << "Disabling texturing.\n";
|
||||
render.set_texture_off(override_priority);
|
||||
} else {
|
||||
nout << "Enabling texturing.\n";
|
||||
render.clear_texture();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_w(CPT_Event) {
|
||||
// 'w' : toggle wireframe.
|
||||
wireframe = !wireframe;
|
||||
if (wireframe) {
|
||||
nout << "Setting wireframe mode.\n";
|
||||
render.set_render_mode_wireframe(override_priority);
|
||||
render.set_two_sided(true, override_priority);
|
||||
} else {
|
||||
nout << "Clearing wireframe mode.\n";
|
||||
render.clear_render_mode();
|
||||
if (!two_sided) {
|
||||
render.clear_two_sided();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_b(CPT_Event) {
|
||||
// 'b' : toggle backfacing.
|
||||
two_sided = !two_sided;
|
||||
if (two_sided) {
|
||||
nout << "Showing back-facing polygons.\n";
|
||||
render.set_two_sided(true, override_priority);
|
||||
} else {
|
||||
nout << "Hiding back-facing polygons.\n";
|
||||
if (!wireframe) {
|
||||
render.clear_two_sided();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_s(CPT_Event) {
|
||||
// 's' : toggle state sorting by putting everything into the 'unsorted' bin.
|
||||
static bool sorting_off = false;
|
||||
|
||||
sorting_off = !sorting_off;
|
||||
if (sorting_off) {
|
||||
nout << "Disabling state sorting.\n";
|
||||
render.set_bin("unsorted", 0, override_priority);
|
||||
} else {
|
||||
nout << "Enabling state sorting.\n";
|
||||
render.clear_bin();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_S(CPT_Event) {
|
||||
// shift 'S' : active PStats.
|
||||
#ifdef DO_PSTATS
|
||||
nout << "Connecting to stats host" << endl;
|
||||
PStatClient::connect();
|
||||
#else
|
||||
nout << "Stats host not supported." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
event_A(CPT_Event) {
|
||||
// shift 'A' : deactive PStats.
|
||||
#ifdef DO_PSTATS
|
||||
if (PStatClient::is_connected()) {
|
||||
nout << "Disconnecting from stats host" << endl;
|
||||
PStatClient::disconnect();
|
||||
} else {
|
||||
nout << "Stats host is already disconnected." << endl;
|
||||
}
|
||||
#else
|
||||
nout << "Stats host not supported." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
event_l(CPT_Event) {
|
||||
// 'l' : toggle lighting.
|
||||
lighting = !lighting;
|
||||
if (lighting) {
|
||||
nout << "Enabling lighting.\n";
|
||||
static bool lights_created = false;
|
||||
|
||||
static PT(AmbientLight) alight;
|
||||
static PT(DirectionalLight) dlight;
|
||||
|
||||
if (!lights_created) {
|
||||
alight = new AmbientLight("ambient");
|
||||
alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
dlight = new DirectionalLight("directional");
|
||||
camera_np.attach_new_node(alight);
|
||||
camera_np.attach_new_node(dlight);
|
||||
|
||||
lights_created = true;
|
||||
}
|
||||
|
||||
// Enable lights on the top node.
|
||||
render.node()->set_attrib(LightAttrib::make(LightAttrib::O_add, alight, dlight));
|
||||
|
||||
} else {
|
||||
nout << "Disabling lighting.\n";
|
||||
// Remove the lights from the top node.
|
||||
render.node()->clear_attrib(LightAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
#include "pandaFramework.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
// First, we need a GraphicsPipe, before we can open a window.
|
||||
PT(GraphicsPipe) pipe = make_pipe();
|
||||
PandaFramework framework;
|
||||
framework.open_framework(argc, argv);
|
||||
framework.set_window_title("Panda Viewer");
|
||||
|
||||
// We also need a GraphicsEngine to manage the rendering process.
|
||||
GraphicsEngine *engine = new GraphicsEngine;
|
||||
WindowFramework *window = framework.open_window();
|
||||
if (window != (WindowFramework *)NULL) {
|
||||
// We've successfully opened a window.
|
||||
|
||||
// Now open a window and get a camera.
|
||||
PT(GraphicsWindow) window = make_window(pipe, engine);
|
||||
PT(qpCamera) camera = make_camera(window);
|
||||
window->enable_keyboard();
|
||||
window->setup_trackball();
|
||||
window->load_models(window->get_render(), argc, argv);
|
||||
window->loop_animations();
|
||||
|
||||
// Now we just need to make a scene graph for the camera to render.
|
||||
render = qpNodePath("render");
|
||||
camera_np = render.attach_new_node(camera);
|
||||
camera->set_scene(render);
|
||||
framework.enable_default_keys();
|
||||
framework.main_loop();
|
||||
}
|
||||
|
||||
// This is maybe here temporarily, and maybe not.
|
||||
render.set_two_sided(0);
|
||||
|
||||
// Set up a data graph for tracking user input.
|
||||
PT(PandaNode) data_root = new PandaNode("data_root");
|
||||
PandaNode *mouse = setup_mouse(data_root, window);
|
||||
setup_trackball(mouse, camera);
|
||||
qpDataGraphTraverser dg_trav;
|
||||
|
||||
// Use an event handler to manage keyboard events.
|
||||
EventHandler event_handler(EventQueue::get_global_event_queue());
|
||||
event_handler.add_hook("escape", event_esc);
|
||||
event_handler.add_hook("q", event_esc);
|
||||
event_handler.add_hook("f", event_f);
|
||||
event_handler.add_hook("t", event_t);
|
||||
event_handler.add_hook("w", event_w);
|
||||
event_handler.add_hook("b", event_b);
|
||||
event_handler.add_hook("s", event_s);
|
||||
event_handler.add_hook("shift-s", event_S);
|
||||
event_handler.add_hook("shift-a", event_A);
|
||||
event_handler.add_hook("l", event_l);
|
||||
|
||||
|
||||
// Put something in the scene graph to look at.
|
||||
get_models(render.node(), argc, argv);
|
||||
|
||||
// If we happened to load up both a character file and its matching
|
||||
// animation file, attempt to bind them together now and start the
|
||||
// animations looping.
|
||||
AnimControlCollection anim_controls;
|
||||
auto_bind(render.node(), anim_controls, ~0);
|
||||
anim_controls.loop_all(true);
|
||||
|
||||
|
||||
// Tick the clock once so we won't count the time spent loading up
|
||||
// files, above, in our frame rate average.
|
||||
ClockObject::get_global_clock()->tick();
|
||||
|
||||
// This is our main update loop. Loop here until someone
|
||||
// (e.g. event_esc) sets run_flag to false.
|
||||
while (run_flag) {
|
||||
dg_trav.traverse(data_root);
|
||||
event_handler.process_events();
|
||||
engine->render_frame();
|
||||
}
|
||||
|
||||
report_frame_rate();
|
||||
delete engine;
|
||||
framework.report_frame_rate(nout);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue