pgraph tweaks, chancfg, modelpool
This commit is contained in:
parent
4ddf472bf8
commit
a7132f9cf4
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "modelPool.cxx"
|
||||
#include "qpmodelPool.cxx"
|
||||
#include "loaderFileType.cxx"
|
||||
#include "loaderFileTypeBam.cxx"
|
||||
#include "loaderFileTypeRegistry.cxx"
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ PUBLISHED:
|
|||
};
|
||||
|
||||
INLINE qpNodePath();
|
||||
INLINE qpNodePath(const string &top_node_name);
|
||||
INLINE qpNodePath(PandaNode *top_node);
|
||||
INLINE qpNodePath(const qpNodePath ©);
|
||||
INLINE void operator = (const qpNodePath ©);
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
|||
_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 ©) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
operator = (const PipelineCyclerBase ©) {
|
||||
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 ©) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
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--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue