pgraph tweaks, chancfg, modelpool

This commit is contained in:
David Rose 2002-03-13 02:11:00 +00:00
parent 4ddf472bf8
commit a7132f9cf4
13 changed files with 767 additions and 41 deletions

View File

@ -17,7 +17,7 @@
////////////////////////////////////////////////////////////////////
INLINE PT_NamedNode ChanConfig::get_group_node(const int node_index) const {
return _group_node[node_index];
return _group_node[node_index];
}
INLINE int ChanConfig::get_group_membership(const int dr_index) const {
return _group_membership[dr_index];
@ -35,3 +35,23 @@
return _graphics_window;
}
INLINE PandaNode *qpChanConfig::get_group_node(const int node_index) const {
return _group_node[node_index];
}
INLINE int qpChanConfig::get_group_membership(const int dr_index) const {
return _group_membership[dr_index];
}
INLINE int qpChanConfig::get_num_groups(void) const {
return _group_node.size();
}
INLINE int qpChanConfig::get_num_drs(void) const {
return _display_region.size();
}
INLINE PT(DisplayRegion) qpChanConfig::get_dr(const int dr_index) const {
return _display_region[dr_index];
}
INLINE PT(GraphicsWindow) qpChanConfig::get_win(void) const {
return _graphics_window;
}

View File

@ -17,20 +17,23 @@
////////////////////////////////////////////////////////////////////
#include "chancfg.h"
#include <notify.h>
#include <displayRegion.h>
#include <graphicsChannel.h>
#include <hardwareChannel.h>
#include <camera.h>
#include <frustum.h>
#include <perspectiveLens.h>
#include <renderRelation.h>
#include <transformTransition.h>
#include <dSearchPath.h>
#include <dconfig.h>
#include <filename.h>
#include "notify.h"
#include "displayRegion.h"
#include "graphicsChannel.h"
#include "hardwareChannel.h"
#include "camera.h"
#include "qpcamera.h"
#include "frustum.h"
#include "perspectiveLens.h"
#include "renderRelation.h"
#include "transformTransition.h"
#include "dSearchPath.h"
#include "dconfig.h"
#include "filename.h"
#include "pt_NamedNode.h"
#include "transformState.h"
#include <algorithm>
#include <pt_NamedNode.h>
Configure(chanconfig);
@ -483,6 +486,283 @@ ChanConfig::ChanConfig(GraphicsPipe* pipe, std::string cfg, Node *render,
return;
}
void qpChanConfig::chan_eval(GraphicsWindow* win, WindowItem& W, LayoutItem& L,
SVec& S,
ChanViewport& V, int hw_offset, int xsize, int ysize,
const qpNodePath &render, bool want_cameras) {
int i = min(L.GetNumRegions(), int(S.size()));
int j;
SVec::iterator k;
std::vector< PT(PandaNode) >camera(W.getNumCameraGroups());
//first camera is special cased to name "camera" for older code
camera[0] = new PandaNode("camera");
for(int icam=1;icam<W.getNumCameraGroups();icam++) {
char dummy[10];//if more than 10^11 groups, you've got bigger problems
sprintf(dummy,"%d",icam);
std::string nodeName = "camera";
nodeName.append(dummy);
camera[icam] = new PandaNode(nodeName);
}
for (j=0, k=S.begin(); j<i; ++j, ++k) {
ChanViewport v(ChanScaleViewport(V, L[j]));
PT(GraphicsChannel) chan;
if ((*k).getHWChan() && W.getHWChans()) {
if ((*k).getChan() == -1) {
chan = win->get_channel(hw_offset);
} else
chan = win->get_channel((*k).getChan());
// HW channels always start with the full area of the channel
v = ChanViewport(0.0f, 1.0f, 0.0f, 1.0f);
} else {
chan = win->get_channel(0);
}
ChanViewport v2(ChanScaleViewport(v, (*k).getViewport()));
PT(GraphicsLayer) layer = chan->make_layer();
PT(DisplayRegion) dr =
layer->make_display_region(v2.left(), v2.right(),
v2.bottom(), v2.top());
if (want_cameras && camera[0] != (PandaNode *)NULL) {
// now make a camera for it
PT(qpCamera) cam = new qpCamera("");
dr->set_qpcamera(qpNodePath(cam));
_display_region.push_back(dr);
SetupFOV fov = (*k).getFOV();
// The distinction between ConsoleSize and DisplaySize
// is to handle display regions with orientations that
// are rotated 90 degrees left or right. For example,
// the model shop cave (LAIR) uses projectors on their
// sides, so that what's horizontal on the console is
// vertical in the cave (Display).
float xConsoleSize = xsize*(v2.right()-v2.left());
float yConsoleSize = ysize*(v2.top()-v2.bottom());
float xDisplaySize, yDisplaySize;
if ( (*k).getOrientation() == SetupItem::Left ||
(*k).getOrientation() == SetupItem::Right ) {
xDisplaySize = yConsoleSize;
yDisplaySize = xConsoleSize;
} else {
xDisplaySize = xConsoleSize;
yDisplaySize = yConsoleSize;
}
fov = ChanResolveFOV(fov, xDisplaySize, yDisplaySize);
if (chancfg_cat->is_debug()) {
chancfg_cat->debug() << "ChanEval:: FOVhoriz = " << fov.getHoriz()
<< " FOVvert = " << fov.getVert() << endl;
chancfg_cat->debug() << "ChanEval:: xsize = " << xsize
<< " ysize = " << ysize << endl;
}
// take care of the orientation
CPT(TransformState) orient;
float hFov, vFov;
switch ((*k).getOrientation()) {
case SetupItem::Up:
hFov = fov.getHoriz(); vFov = fov.getVert();
break;
case SetupItem::Down:
hFov = fov.getHoriz(); vFov = fov.getVert();
orient = TransformState::make_mat
(LMatrix4f::rotate_mat_normaxis(180.0f, LVector3f::forward()));
break;
case SetupItem::Left:
// vertical and horizontal FOV are being switched
hFov = fov.getVert(); vFov = fov.getHoriz();
orient = TransformState::make_mat
(LMatrix4f::rotate_mat_normaxis(90.0f, LVector3f::forward()));
break;
case SetupItem::Right:
// vertical and horizontal FOV are being switched
hFov = fov.getVert(); vFov = fov.getHoriz();
orient = TransformState::make_mat
(LMatrix4f::rotate_mat_normaxis(-90.0f, LVector3f::forward()));
break;
}
PT(Lens) lens = new PerspectiveLens;
lens->set_fov(hFov, vFov);
lens->set_near_far(1.0f, 10000.0f);
cam->set_lens(lens);
// hfov and vfov for camera are switched from what was specified
// if the orientation is sideways.
if (chancfg_cat->is_debug())
chancfg_cat->debug() << "ChanEval:: camera hfov = "
<< lens->get_hfov() << " vfov = "
<< lens->get_vfov() << endl;
cam->set_scene(render);
camera[W.getCameraGroup(j)]->add_child(cam);
if (orient != (TransformState *)NULL) {
cam->set_transform(orient);
}
}
}
_group_node = camera;
return;
}
qpChanConfig::qpChanConfig(GraphicsPipe* pipe, std::string cfg, const qpNodePath &render,
ChanCfgOverrides& overrides) {
ReadChanConfigData();
// check to make sure we know everything we need to
if (!ConfigDefined(cfg)) {
chancfg_cat.error()
<< "no window configuration called '" << cfg << "'" << endl;
_graphics_window = (GraphicsWindow*)0;
return;
}
WindowItem W = (*WindowDB)[cfg];
std::string l = W.getLayout();
if (!LayoutDefined(l)) {
chancfg_cat.error()
<< "No layout called '" << l << "'" << endl;
_graphics_window = (GraphicsWindow*)0;
return;
}
LayoutItem L = (*LayoutDB)[l];
SetupSyms s = W.getSetups();
if (!ChanCheckSetups(s)) {
chancfg_cat.error() << "Setup failure" << endl;
_graphics_window = (GraphicsWindow*)0;
return;
}
SVec S;
S.reserve(s.size());
for (SetupSyms::iterator i=s.begin(); i!=s.end(); ++i)
S.push_back((*SetupDB)[(*i)]);
// get the window data
int sizeX = chanconfig.GetInt("win-width", -1);
int sizeY = chanconfig.GetInt("win-height", -1);
if (overrides.defined(ChanCfgOverrides::SizeX))
sizeX = overrides.getInt(ChanCfgOverrides::SizeX);
if (overrides.defined(ChanCfgOverrides::SizeY))
sizeY = overrides.getInt(ChanCfgOverrides::SizeY);
if (sizeX < 0) {
if (sizeY < 0) {
if(chancfg_cat.is_debug())
chancfg_cat.debug() << "Using default chan-window size\n";
// take the default size
sizeX = W.getSizeX();
sizeY = W.getSizeY();
} else {
// vertical size is defined, compute horizontal keeping the aspect from
// the default
sizeX = (W.getSizeX() * sizeY) / W.getSizeY();
}
} else if (sizeY < 0) {
// horizontal size is defined, compute vertical keeping the aspect from the
// default
sizeY = (W.getSizeY() * sizeX) / W.getSizeX();
}
int origX = chanconfig.GetInt("win-origin-x");
int origY = chanconfig.GetInt("win-origin-y");
origX = overrides.defined(ChanCfgOverrides::OrigX) ?
overrides.getInt(ChanCfgOverrides::OrigX) : origX;
origY = overrides.defined(ChanCfgOverrides::OrigY) ?
overrides.getInt(ChanCfgOverrides::OrigY) : origY;
bool border = !chanconfig.GetBool("no-border", !W.getBorder());
bool fullscreen = chanconfig.GetBool("fullscreen", false);
bool use_cursor = chanconfig.GetBool("cursor-visible", W.getCursor());
int want_depth_bits = chanconfig.GetInt("want-depth-bits", 1);
int want_color_bits = chanconfig.GetInt("want-color-bits", 1);
// visual? nope, that's handled with the mode.
uint mask = 0x0; // ?! this really should come from the win config
mask = overrides.defined(ChanCfgOverrides::Mask) ?
overrides.getUInt(ChanCfgOverrides::Mask) : mask;
std::string title = cfg;
title = overrides.defined(ChanCfgOverrides::Title) ?
overrides.getString(ChanCfgOverrides::Title) : title;
GraphicsWindow::Properties props;
props._xorg = origX;
props._yorg = origY;
props._xsize = sizeX;
props._ysize = sizeY;
props._title = title;
props._mask = mask;
props._border = border;
props._fullscreen = fullscreen;
props._want_depth_bits = want_depth_bits;
props._want_color_bits = want_color_bits;
props._bCursorIsVisible = use_cursor;
// stereo prep?
// DVR prep?
bool want_cameras = overrides.defined(ChanCfgOverrides::Cameras) ?
overrides.getBool(ChanCfgOverrides::Cameras) : true;
// open that sucker
PT(GraphicsWindow) win = pipe->make_window(props);
if(win == (GraphicsWindow *)NULL) {
chancfg_cat.error() << "Could not create window" << endl;
_graphics_window = (GraphicsWindow *)NULL;
return;
}
// make channels and display regions
ChanViewport V(0.0f, 1.0f, 0.0f, 1.0f);
chan_eval(win, W, L, S, V, W.getChanOffset()+1, sizeX, sizeY,
render, want_cameras);
for(size_t dr_index=0; dr_index<_display_region.size(); dr_index++)
_group_membership.push_back(W.getCameraGroup(dr_index));
// sanity check
if (config_sanity_check) {
nout << "ChanConfig Sanity check:" << endl
<< "window - " << (void*)win << endl
<< " width = " << win->get_width() << " height = " << win->get_height() << endl
<< " xorig = " << win->get_xorg() << " yorig = " << win->get_yorg()<< endl;
int max_channel_index = win->get_max_channel_index();
for (int c = 0; c < max_channel_index; c++) {
if (win->is_channel_defined(c)) {
GraphicsChannel *chan = win->get_channel(c);
nout << " Chan - " << (void*)chan << endl
<< " window = " << (void*)(chan->get_window()) << endl
<< " active = " << chan->is_active() << endl;
int num_layers = chan->get_num_layers();
for (int l = 0; l < num_layers; l++) {
GraphicsLayer *layer = chan->get_layer(l);
nout << " Layer - " << (void*)layer << endl
<< " channel = " << (void*)(layer->get_channel()) << endl
<< " active = " << layer->is_active() << endl;
int num_drs = layer->get_num_drs();
for (int d = 0; d < num_drs; d++) {
DisplayRegion *dr = layer->get_dr(d);
nout << " DR - " << (void*)dr << endl
<< " layer = " << (void*)(dr->get_layer()) << endl;
float ll, rr, bb, tt;
dr->get_dimensions(ll, rr, bb, tt);
nout << " (" << ll << " " << rr << " " << bb << " " << tt << ")" << endl
<< " camera = " << (void*)(dr->get_camera()) << endl;
Camera* cmm = dr->get_camera();
if (cmm != (Camera*)0L) {
nout << " active = " << cmm->is_active() << endl;
int num_cam_drs = cmm->get_num_drs();
for (int cd = 0; cd < num_cam_drs; cd++)
nout << " dr = " << (void*)cmm->get_dr(cd) << endl;
}
nout << " active = " << dr->is_active() << endl;
}
}
}
}
}
_graphics_window = win;
return;
}

View File

@ -19,16 +19,18 @@
#ifndef __CHANCFG_H__
#define __CHANCFG_H__
#include <pandabase.h>
#include "pandabase.h"
#include "chanlayout.h"
#include "chansetup.h"
#include "chanwindow.h"
#include "chanshare.h"
#include <graphicsPipe.h>
#include <graphicsWindow.h>
#include <pt_NamedNode.h>
#include "graphicsPipe.h"
#include "graphicsWindow.h"
#include "pt_NamedNode.h"
#include "pandaNode.h"
#include "qpnodePath.h"
#include "pmap.h"
@ -104,6 +106,7 @@ extern ChanCfgOverrides ChanOverrideNone;
typedef pvector<SetupItem> SVec;
class NamedNode;
class EXPCL_PANDA ChanConfig
{
private:
@ -125,6 +128,27 @@ PUBLISHED:
INLINE PT(GraphicsWindow) get_win(void) const;
};
class EXPCL_PANDA qpChanConfig
{
private:
std::vector< PT(PandaNode) > _group_node;
std::vector< PT(DisplayRegion) > _display_region;
std::vector<int> _group_membership;
PT(GraphicsWindow) _graphics_window;
void chan_eval(GraphicsWindow* win, WindowItem& W, LayoutItem& L,
SVec& S, ChanViewport& V, int hw_offset,
int xsize, int ysize, const qpNodePath &render, bool want_cameras);
PUBLISHED:
qpChanConfig(GraphicsPipe*, std::string, const qpNodePath &render,
ChanCfgOverrides& = ChanOverrideNone);
INLINE PandaNode *get_group_node(const int node_index) const;
INLINE int get_group_membership(const int dr_index) const;
INLINE int get_num_groups(void) const;
INLINE int get_num_drs(void) const;
INLINE PT(DisplayRegion) get_dr(const int dr_index) const;
INLINE PT(GraphicsWindow) get_win(void) const;
};
#include "chancfg.I"
#endif /* __CHANCFG_H__ */

View File

@ -9,19 +9,23 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
bamFile.I bamFile.h config_loader.h loader.I loader.h \
loaderFileType.h loaderFileTypeBam.h \
loaderFileTypeRegistry.h modelPool.I modelPool.h
bamFile.I bamFile.h config_loader.h loader.I loader.h \
loaderFileType.h loaderFileTypeBam.h \
loaderFileTypeRegistry.h \
modelPool.I modelPool.h \
qpmodelPool.I qpmodelPool.h
#define INCLUDED_SOURCES \
bamFile.cxx config_loader.cxx loader.cxx loaderFileType.cxx \
loaderFileTypeBam.cxx loaderFileTypeRegistry.cxx \
modelPool.cxx
bamFile.cxx config_loader.cxx loader.cxx loaderFileType.cxx \
loaderFileTypeBam.cxx loaderFileTypeRegistry.cxx \
modelPool.cxx \
qpmodelPool.cxx
#define INSTALL_HEADERS \
bamFile.I bamFile.h loader.I loader.h loaderFileType.h \
loaderFileTypeBam.h loaderFileTypeRegistry.h modelPool.I \
modelPool.h
loaderFileTypeBam.h loaderFileTypeRegistry.h \
modelPool.I modelPool.h \
qpmodelPool.I qpmodelPool.h
#define IGATESCAN all

View File

@ -1,5 +1,6 @@
#include "modelPool.cxx"
#include "qpmodelPool.cxx"
#include "loaderFileType.cxx"
#include "loaderFileTypeBam.cxx"
#include "loaderFileTypeRegistry.cxx"

View File

@ -0,0 +1,131 @@
// Filename: qpmodelPool.I
// Created by: drose (12Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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: qpModelPool::has_model
// Access: Public, Static
// Description: Returns true if the model has ever been loaded,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool qpModelPool::
has_model(const string &filename) {
return get_ptr()->ns_has_model(filename);
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::verify_model
// Access: Public, Static
// Description: Loads the given filename up as a model, if it has
// not already been loaded, and returns true to indicate
// success, or false to indicate failure. If this
// returns true, it is guaranteed that a subsequent call
// to load_model() with the same model name will
// return a valid Node pointer.
////////////////////////////////////////////////////////////////////
INLINE bool qpModelPool::
verify_model(const string &filename) {
return load_model(filename) != (PandaNode *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::load_model
// Access: Public, Static
// Description: Loads the given filename up as a model, if it has
// not already been loaded, and returns the new model.
// If a model with the same filename was previously
// loaded, returns that one instead. If the model
// file cannot be found, returns NULL.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *qpModelPool::
load_model(const string &filename) {
return get_ptr()->ns_load_model(filename);
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::add_model
// Access: Public, Static
// Description: Adds the indicated already-loaded model to the
// pool. The model will always replace any
// previously-loaded model in the pool that had the
// same filename.
////////////////////////////////////////////////////////////////////
INLINE void qpModelPool::
add_model(const string &filename, PandaNode *model) {
get_ptr()->ns_add_model(filename, model);
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::release_model
// Access: Public, Static
// Description: Removes the indicated model from the pool,
// indicating it will never be loaded again; the model
// may then be freed. If this function is never called,
// a reference count will be maintained on every model
// every loaded, and models will never be freed.
////////////////////////////////////////////////////////////////////
INLINE void qpModelPool::
release_model(const string &filename) {
get_ptr()->ns_release_model(filename);
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::release_all_models
// Access: Public, Static
// Description: Releases all models in the pool and restores the
// pool to the empty state.
////////////////////////////////////////////////////////////////////
INLINE void qpModelPool::
release_all_models() {
get_ptr()->ns_release_all_models();
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::garbage_collect
// Access: Public, Static
// Description: Releases only those models in the pool that have a
// reference count of exactly 1; i.e. only those
// models that are not being used outside of the pool.
// Returns the number of models released.
////////////////////////////////////////////////////////////////////
INLINE int qpModelPool::
garbage_collect() {
return get_ptr()->ns_garbage_collect();
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::list_contents
// Access: Public, Static
// Description: Lists the contents of the model pool to the
// indicated output stream.
////////////////////////////////////////////////////////////////////
INLINE void qpModelPool::
list_contents(ostream &out) {
get_ptr()->ns_list_contents(out);
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::Constructor
// Access: Private
// Description: The constructor is not intended to be called
// directly; there's only supposed to be one qpModelPool
// in the universe and it constructs itself.
////////////////////////////////////////////////////////////////////
INLINE qpModelPool::
qpModelPool() {
}

View File

@ -0,0 +1,161 @@
// Filename: qpmodelPool.cxx
// Created by: drose (12Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "qpmodelPool.h"
#include "loader.h"
#include "config_loader.h"
qpModelPool *qpModelPool::_global_ptr = (qpModelPool *)NULL;
static Loader _qpmodel_loader;
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_has_model
// Access: Private
// Description: The nonstatic implementation of has_model().
////////////////////////////////////////////////////////////////////
bool qpModelPool::
ns_has_model(const string &filename) {
Models::const_iterator ti;
ti = _models.find(filename);
if (ti != _models.end()) {
// This model was previously loaded.
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_load_model
// Access: Private
// Description: The nonstatic implementation of load_model().
////////////////////////////////////////////////////////////////////
PandaNode *qpModelPool::
ns_load_model(const string &filename) {
Models::const_iterator ti;
ti = _models.find(filename);
if (ti != _models.end()) {
// This model was previously loaded.
return (*ti).second;
}
loader_cat.info()
<< "Loading model " << filename << "\n";
PT(PandaNode) node = _qpmodel_loader.qpload_sync(filename);
if (node.is_null()) {
// This model was not found.
return (PandaNode *)NULL;
}
_models[filename] = node;
return node;
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_add_model
// Access: Private
// Description: The nonstatic implementation of add_model().
////////////////////////////////////////////////////////////////////
void qpModelPool::
ns_add_model(const string &filename, PandaNode *model) {
// We blow away whatever model was there previously, if any.
_models[filename] = model;
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_release_model
// Access: Private
// Description: The nonstatic implementation of release_model().
////////////////////////////////////////////////////////////////////
void qpModelPool::
ns_release_model(const string &filename) {
Models::iterator ti;
ti = _models.find(filename);
if (ti != _models.end()) {
_models.erase(ti);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_release_all_models
// Access: Private
// Description: The nonstatic implementation of release_all_models().
////////////////////////////////////////////////////////////////////
void qpModelPool::
ns_release_all_models() {
_models.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_garbage_collect
// Access: Private
// Description: The nonstatic implementation of garbage_collect().
////////////////////////////////////////////////////////////////////
int qpModelPool::
ns_garbage_collect() {
int num_released = 0;
Models new_set;
Models::iterator ti;
for (ti = _models.begin(); ti != _models.end(); ++ti) {
PandaNode *node = (*ti).second;
if (node->get_ref_count() == 1) {
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Releasing " << (*ti).first << "\n";
}
num_released++;
} else {
new_set.insert(new_set.end(), *ti);
}
}
_models.swap(new_set);
return num_released;
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::ns_list_contents
// Access: Private
// Description: The nonstatic implementation of list_contents().
////////////////////////////////////////////////////////////////////
void qpModelPool::
ns_list_contents(ostream &out) {
out << _models.size() << " models:\n";
Models::iterator ti;
for (ti = _models.begin(); ti != _models.end(); ++ti) {
out << " " << (*ti).first
<< " (count = " << (*ti).second->get_ref_count() << ")\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpModelPool::get_ptr
// Access: Private, Static
// Description: Initializes and/or returns the global pointer to the
// one qpModelPool object in the system.
////////////////////////////////////////////////////////////////////
qpModelPool *qpModelPool::
get_ptr() {
if (_global_ptr == (qpModelPool *)NULL) {
_global_ptr = new qpModelPool;
}
return _global_ptr;
}

View File

@ -0,0 +1,85 @@
// Filename: qpmodelPool.h
// Created by: drose (12Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 qpMODELPOOL_H
#define qpMODELPOOL_H
#include "pandabase.h"
#include "filename.h"
#include "pandaNode.h"
#include "pointerTo.h"
#include "pmap.h"
////////////////////////////////////////////////////////////////////
// Class : ModelPool
// Description : This is the preferred interface for loading models.
// It unifies all references to the same filename, so
// that multiple attempts to load the same model will
// return the same pointer. Note that the default
// behavior is thus to make instances: use with caution.
// Use the copy_subgraph() method on Node (or use
// NodePath::copy_to) to make modifiable copies of the
// node.
//
// Unlike TexturePool, this class does not automatically
// resolve the model filenames before loading, so a
// relative path and an absolute path to the same model
// will appear to be different filenames.
//
// This does not presently support asynchronous loading,
// although it wouldn't be *too* difficult to add.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpModelPool {
PUBLISHED:
INLINE static bool has_model(const string &filename);
INLINE static bool verify_model(const string &filename);
INLINE static PandaNode *load_model(const string &filename);
INLINE static void add_model(const string &filename, PandaNode *model);
INLINE static void release_model(const string &filename);
INLINE static void release_all_models();
INLINE static int garbage_collect();
INLINE static void list_contents(ostream &out);
private:
INLINE qpModelPool();
bool ns_has_model(const string &filename);
PandaNode *ns_load_model(const string &filename);
void ns_add_model(const string &filename, PandaNode *model);
void ns_release_model(const string &filename);
void ns_release_all_models();
int ns_garbage_collect();
void ns_list_contents(ostream &out);
static qpModelPool *get_ptr();
static qpModelPool *_global_ptr;
typedef pmap<string, PT(PandaNode) > Models;
Models _models;
};
#include "qpmodelPool.I"
#endif

View File

@ -487,6 +487,7 @@ add_child(PandaNode *child_node, int sort) {
{
PT(PandaNode) keep_child = child_node;
remove_child(child_node);
CDWriter cdata(_cycler);
CDWriter cdata_child(child_node->_cycler);

View File

@ -32,13 +32,25 @@ qpNodePath() :
{
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::Constructor
// Access: Published
// Description: This constructs an empty qpNodePath with a single
// node. An ordinary PandaNode is created with the
// indicated name.
////////////////////////////////////////////////////////////////////
INLINE qpNodePath::
qpNodePath(const string &top_node_name) :
_error_type(ET_ok)
{
PandaNode *top_node = new PandaNode(top_node_name);
_head = top_node->get_generic_component();
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::Constructor
// Access: Published
// Description: This constructs an empty qpNodePath with a single node.
// This path may now be extended by repeatedly calling
// push_back() with each node below that node in
// sequence.
//
// If the Node pointer is NULL, this quietly creates an
// empty qpNodePath.

View File

@ -68,6 +68,7 @@ PUBLISHED:
};
INLINE qpNodePath();
INLINE qpNodePath(const string &top_node_name);
INLINE qpNodePath(PandaNode *top_node);
INLINE qpNodePath(const qpNodePath &copy);
INLINE void operator = (const qpNodePath &copy);

View File

@ -31,8 +31,7 @@ PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) :
_data(initial_data),
_pipeline(pipeline),
_read_count(0),
_write_count(0),
_stage_count(0)
_write_count(0)
{
if (_pipeline == (Pipeline *)NULL) {
_pipeline = Pipeline::get_render_pipeline();
@ -49,8 +48,7 @@ PipelineCyclerBase(const PipelineCyclerBase &copy) :
_data(copy._data->make_copy()),
_pipeline(copy._pipeline),
_read_count(0),
_write_count(0),
_stage_count(0)
_write_count(0)
{
}
@ -61,7 +59,7 @@ PipelineCyclerBase(const PipelineCyclerBase &copy) :
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerBase::
operator = (const PipelineCyclerBase &copy) {
nassertv(_read_count == 0 && _write_count == 0 && _stage_count == 0);
nassertv(_read_count == 0 && _write_count == 0);
_data = copy._data->make_copy();
_pipeline = copy._pipeline;
}
@ -73,7 +71,7 @@ operator = (const PipelineCyclerBase &copy) {
////////////////////////////////////////////////////////////////////
INLINE PipelineCyclerBase::
~PipelineCyclerBase() {
nassertv(_read_count == 0 && _write_count == 0 && _stage_count == 0);
nassertv(_read_count == 0 && _write_count == 0);
}
////////////////////////////////////////////////////////////////////
@ -92,7 +90,9 @@ read() const {
// This function isn't truly const, but it doesn't change the data
// in any meaningful way, so we pretend it is.
((PipelineCyclerBase *)this)->_read_count++;
nassertr(_write_count == 0, _data);
// It's not an error to grab a read pointer while someone else holds
// a read or a write pointer.
return _data;
}
@ -146,8 +146,14 @@ release_read(const CycleData *pointer) const {
INLINE CycleData *PipelineCyclerBase::
write() {
_write_count++;
// It's an error to grab a write pointer while someone else holds a
// read pointer, because doing so may invalidate the read pointer.
nassertr(_read_count == 0, _data);
nassertr(_write_count == 1, _data);
// It's not an error to do this while someone else holds a write
// pointer, however.
return _data;
}
@ -215,7 +221,7 @@ is_stage_unique(int n) const {
INLINE CycleData *PipelineCyclerBase::
write_stage(int n) {
nassertr(n == 0, (CycleData *)NULL);
_stage_count++;
_write_count++;
return _data;
}
@ -228,8 +234,8 @@ write_stage(int n) {
INLINE void PipelineCyclerBase::
release_write_stage(int n, CycleData *pointer) {
nassertv(n == 0 && pointer == _data);
nassertv(_stage_count > 0);
_stage_count--;
nassertv(_write_count > 0);
_write_count--;
}
////////////////////////////////////////////////////////////////////

View File

@ -62,7 +62,7 @@ public:
private:
PT(CycleData) _data;
Pipeline *_pipeline;
short _read_count, _write_count, _stage_count;
short _read_count, _write_count;
#endif // DO_PIPELINING
};