integrate AviTexture better with Panda, rename to OpenCVTexture

This commit is contained in:
David Rose 2005-09-21 23:53:07 +00:00
parent f91ee87026
commit a7b1f14e80
104 changed files with 2583 additions and 1693 deletions

View File

@ -6,7 +6,7 @@
#define DIR_TYPE metalib
#define BUILDING_DLL BUILDING_PANDA
#define USE_PACKAGES net cv
#define USE_PACKAGES net
#define COMPONENT_LIBS \
recorder pgraph \

View File

@ -16,92 +16,6 @@
//
////////////////////////////////////////////////////////////////////
#include <math.h>
////////////////////////////////////////////////////////////////////
// Function: AnimControl::set_play_rate
// Access: Published
// Description: Sets the speed of the animation, relative to its
// "normal" speed. Setting this number to 2.0 plays it
// twice as fast, 0.5 half as fast. -1.0 plays it
// backwards, and 0.0 stops it. The change is actually
// retroactive to the last frame.
//
// If you are going to change the play_rate from a
// positive number to a negative number, or vice-versa,
// you should do this before starting the animation.
// The various flavors of play() and loop() do slightly
// different behavior based on whether play_rate is
// positive or negative.
////////////////////////////////////////////////////////////////////
INLINE void AnimControl::
set_play_rate(double play_rate) {
_play_rate = play_rate;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_play_rate
// Access: Published
// Description: Returns the current speed of the animation. See
// set_play_rate().
////////////////////////////////////////////////////////////////////
INLINE double AnimControl::
get_play_rate() const {
return _play_rate;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_frame_rate
// Access: Published
// Description: Returns the actual frame rate of the animation, based
// on the play_rate (see set_play_rate()) and the
// animation's base frame rate (see
// AnimBundle::get_base_frame_rate()). This is in
// frames per second.
////////////////////////////////////////////////////////////////////
INLINE double AnimControl::
get_frame_rate() const {
return get_play_rate() * get_anim()->get_base_frame_rate();
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_frame
// Access: Published
// Description: Returns the current frame number of the animation.
////////////////////////////////////////////////////////////////////
INLINE int AnimControl::
get_frame() const {
// We have to use floor() here instead of simply casting the number
// to an integer, becase the frame number might have become
// negative.
return (int)cfloor(_frame + 0.0001);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_num_frames
// Access: Published
// Description: Returns the number of frames of animation. This is
// actually just extracted directly from the AnimBundle;
// the function is duplicated here for convenience. The
// frame number will never be outside the range 0 <=
// frame < get_num_frames().
////////////////////////////////////////////////////////////////////
INLINE int AnimControl::
get_num_frames() const {
return get_anim()->get_num_frames();
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::is_playing
// Access: Published
// Description: Returns true if the AnimControl is currently playing,
// false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool AnimControl::
is_playing() const {
return _playing;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_anim

View File

@ -16,16 +16,11 @@
//
////////////////////////////////////////////////////////////////////
#include "animControl.h"
#include "animChannelBase.h"
#include "partBundle.h"
#include "config_chan.h"
#include "event.h"
#include "throw_event.h"
TypeHandle AnimControl::_type_handle;
////////////////////////////////////////////////////////////////////
@ -42,18 +37,15 @@ AnimControl(PartBundle *part, AnimBundle *anim, int channel_index) {
_part = part;
_anim = anim;
_channel_index = channel_index;
_play_rate = 1.0f;
_frame = 0.0f;
_as_of_time = 0.0f;
_playing = false;
set_frame_rate(_anim->get_base_frame_rate());
set_num_frames(_anim->get_num_frames());
_marked_frame = -1;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::Destructor
// Access: Published
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
AnimControl::
@ -61,296 +53,6 @@ AnimControl::
get_part()->set_control_effect(this, 0.0f);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::play
// Access: Published
// Description: Runs the entire animation from beginning to end and
// stops, throwing the stop event (if it is non-NULL).
////////////////////////////////////////////////////////////////////
void AnimControl::
play(const CPT_Event &stop_event) {
nassertv(get_num_frames() > 0);
if (get_play_rate() < 0.0f) {
play(get_num_frames()-1, 0, stop_event);
} else {
play(0, get_num_frames()-1, stop_event);
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::play
// Access: Published
// Description: Runs the animation from the frame "from" to and
// including the frame "to", at which point the
// animation is stopped and the indicated stop event is
// thrown (if it is non-NULL). If the to frame is less
// than the from frame (unless play_rate is negative),
// the animation will wrap around the end and begins
// again at the beginning before the animation stops.
////////////////////////////////////////////////////////////////////
void AnimControl::
play(int from, int to, const CPT_Event &stop_event) {
nassertv(get_num_frames() > 0);
nassertv(from >= 0 && from < get_num_frames());
nassertv(to >= 0 && to < get_num_frames());
_as_of_time = ClockObject::get_global_clock()->get_frame_time();
_playing = true;
_actions = _user_actions;
if (stop_event != (Event*)0L) {
insert_event_action(_actions, to, stop_event);
}
insert_stop_action(_actions, to);
get_part()->control_activated(this);
set_frame(from);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::loop
// Access: Published
// Description: Starts the entire animation looping. If restart is
// true, the animation is restarted from the beginning;
// otherwise, it continues from the current frame.
////////////////////////////////////////////////////////////////////
void AnimControl::
loop(bool restart) {
nassertv(get_num_frames() > 0);
_as_of_time = ClockObject::get_global_clock()->get_frame_time();
_playing = true;
_actions = _user_actions;
get_part()->control_activated(this);
if (restart) {
if (get_play_rate() < 0.0f) {
set_frame(get_num_frames() - 1);
} else {
set_frame(0);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::loop
// Access: Published
// Description: Loops the animation from the frame "from" to and
// including the frame "to", indefinitely. If restart
// is true, the animation is restarted from the
// beginning; otherwise, it continues from the current
// frame.
////////////////////////////////////////////////////////////////////
void AnimControl::
loop(bool restart, int from, int to) {
nassertv(get_num_frames() > 0);
nassertv(from >= 0 && from < get_num_frames());
nassertv(to >= 0 && to < get_num_frames());
_as_of_time = ClockObject::get_global_clock()->get_frame_time();
_playing = true;
_actions = _user_actions;
if (get_play_rate() < 0.0f) {
// If we're playing backward, we need to set up the loop a little
// differently.
if ((to == 0 && from == get_num_frames()-1) ||
(to == from-1)) {
// In this case, the user has specified to loop over the whole
// range of animation. We don't need a special jump action to
// handle this.
} else {
// Otherwise, set up a jump action to effect the loop. This isn't
// completely accurate, since it will always jump exactly to the
// first frame of the loop, no matter how many frames past the end
// we'd gotten to, but it should be reasonably close, especially
// if the number of frames in the loop is large enough and/or the
// frame rate is high enough.
insert_jump_action(_actions, (to-1+get_num_frames())%get_num_frames(),
from);
}
} else {
if ((from == 0 && to == get_num_frames()-1) ||
(from == to-1)) {
// In this case, the user has specified to loop over the whole
// range of animation. We don't need a special jump action to
// handle this.
} else {
// Otherwise, set up a jump action to effect the loop. This isn't
// completely accurate, since it will always jump exactly to the
// first frame of the loop, no matter how many frames past the end
// we'd gotten to, but it should be reasonably close, especially
// if the number of frames in the loop is large enough and/or the
// frame rate is high enough.
insert_jump_action(_actions, (to+1)%get_num_frames(), from);
}
}
get_part()->control_activated(this);
if (restart) {
set_frame(from);
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::pingpong
// Access: Published
// Description: Loops the animation from the frame "from" to and
// including the frame "to", and then back in the
// opposite direction, indefinitely.
////////////////////////////////////////////////////////////////////
void AnimControl::
pingpong(bool restart, int from, int to) {
if (from == to) {
pose(from);
return;
}
nassertv(get_num_frames() > 0);
nassertv(from >= 0 && from < get_num_frames());
nassertv(to >= 0 && to < get_num_frames());
_as_of_time = ClockObject::get_global_clock()->get_frame_time();
_playing = true;
_actions = _user_actions;
insert_forward_action(_actions, from);
insert_backward_action(_actions, to);
get_part()->control_activated(this);
if (restart) {
set_frame(from);
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::stop
// Access: Published
// Description: Stops a currently playing or looping animation right
// where it is. The animation remains posed at the
// current frame, and no event is thrown.
////////////////////////////////////////////////////////////////////
void AnimControl::
stop() {
_playing = false;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::pose
// Access: Published
// Description: Sets the animation to the indicated frame and holds
// it there.
////////////////////////////////////////////////////////////////////
void AnimControl::
pose(int frame) {
int num_frames = get_num_frames();
nassertv(num_frames > 0);
// Modulo the number of frames.
frame = (int)(frame - cfloor(frame / num_frames) * num_frames);
nassertv(frame >= 0 && frame < num_frames);
_as_of_time = ClockObject::get_global_clock()->get_frame_time();
_playing = false;
_actions = _user_actions;
get_part()->control_activated(this);
set_frame(frame);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::add_event
// Access: Published
// Description: Adds the indicated event to the list of events that
// will be called whenever the animation reaches the
// indicated frame number. Once added, the event will
// persist until it is removed via remove_event() or
// remove_all_events().
////////////////////////////////////////////////////////////////////
void AnimControl::
add_event(int frame, const CPT_Event &event) {
insert_event_action(_user_actions, frame, event);
if (_playing) {
insert_event_action(_actions, frame, event);
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::remove_event
// Access: Published
// Description: Removes all events found that match the indicated
// event name, and returns the number of events
// removed.
////////////////////////////////////////////////////////////////////
int AnimControl::
remove_event(const string &event_name) {
Actions new_actions;
int removed = 0;
Actions::const_iterator ai;
for (ai = _user_actions.begin(); ai != _user_actions.end(); ++ai) {
const Action &action = (*ai).second;
if (action._type == AT_event &&
action._event->get_name() == event_name) {
// Remove this event by not copying it to new_actions.
removed++;
} else {
// Preserve this event.
new_actions.insert(*ai);
}
}
if (removed != 0) {
_user_actions.swap(new_actions);
if (_playing) {
new_actions.clear();
int p_removed = 0;
for (ai = _actions.begin(); ai != _actions.end(); ++ai) {
const Action &action = (*ai).second;
if (action._type == AT_event &&
action._event->get_name() == event_name) {
// Remove this event by not copying it to new_actions.
p_removed++;
} else {
// Preserve this event.
new_actions.insert(*ai);
}
}
nassertr(p_removed == removed, removed);
_actions.swap(new_actions);
}
}
return removed;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::remove_all_events
// Access: Published
// Description: Removes all user-defined event messages. However, if
// called while an animation is running, this will not
// take effect until the animation is stopped and
// restarted.
////////////////////////////////////////////////////////////////////
void AnimControl::
remove_all_events() {
_user_actions.clear();
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_part
// Access: Published
@ -370,77 +72,11 @@ get_part() const {
void AnimControl::
output(ostream &out) const {
out << "AnimControl(" << get_part()->get_name()
<< ", " << get_anim()->get_name() << ")";
<< ", " << get_anim()->get_name() << ": ";
AnimInterface::output(out);
out << ")";
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::advance_time
// Access: Public
// Description: Tells the AnimControl what time it is. This
// recomputes the frame number according to the amount
// of time elapsed since last time. Until this function
// is called, the frame number will not increment. The
// time passed to this function must be nondecreasing;
// it is an error to call it with a value less than a
// previously-passed value.
////////////////////////////////////////////////////////////////////
void AnimControl::
advance_time(double time) {
double elapsed_time = time - _as_of_time;
double elapsed_frames = elapsed_time * get_frame_rate();
_as_of_time = time;
if (_playing && elapsed_frames != 0.0f) {
int orig_frame = get_frame();
_frame += elapsed_frames;
double num_frames = (double)get_num_frames();
int new_frame = get_frame();
// Now call all the actions.
if (elapsed_frames < 0.0f) {
// If we're playing the animation backward, we have to check the
// actions in reverse order.
if (new_frame >= 0) {
do_actions_backward(orig_frame-1, new_frame);
} else {
if (do_actions_backward(orig_frame-1, 0)) {
// floor() is correct here, instead of simply an integer
// cast, because we are using floating-point arithmetic
// anyway (no need to convert to integer format and back
// again), and because we need correct behavior when the
// frame number is negative.
_frame = _frame - cfloor(_frame / num_frames) * num_frames;
new_frame = get_frame();
do_actions_backward(get_num_frames(), new_frame);
}
}
} else {
// Normally, we'll be playing the animation forward.
if (new_frame < get_num_frames()) {
do_actions_forward(orig_frame+1, new_frame);
} else {
if (do_actions_forward(orig_frame+1, get_num_frames()-1)) {
// floor() is correct here, instead of simply an integer
// cast, because we are using floating-point arithmetic
// anyway (no need to convert to integer format and back
// again), and because we need correct behavior when the
// frame number is negative.
_frame = _frame - cfloor(_frame / num_frames) * num_frames;
new_frame = get_frame();
do_actions_forward(0, new_frame);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::channel_has_changed
// Access: Public
@ -457,7 +93,6 @@ channel_has_changed(AnimChannelBase *channel) const {
return channel->has_changed(_marked_frame, this_frame);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::mark_channels
// Access: Public
@ -469,307 +104,14 @@ mark_channels() {
_marked_frame = get_frame();
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::insert_event_action
// Access: Private, Static
// Description: Inserts an "event" action at the indicated frame
// number. The event will be thrown as the animation
// reaches the indicated frame number.
// Function: AnimControl::animation_activated
// Access: Protected, Virtual
// Description: This is provided as a callback method for when the
// user calls one of the play/loop/pose type methods to
// start the animation playing.
////////////////////////////////////////////////////////////////////
void AnimControl::
insert_event_action(Actions &actions, int frame, const CPT_Event &event) {
Action new_action;
new_action._type = AT_event;
new_action._event = event;
actions.insert(pair<int, Action>(frame, new_action));
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::insert_stop_action
// Access: Private, Static
// Description: Inserts a "stop" action at the indicated frame
// number. The animation will stop as soon as it
// reaches the indicated frame number, traveling from
// either direction.
////////////////////////////////////////////////////////////////////
void AnimControl::
insert_stop_action(Actions &actions, int frame) {
Action new_action;
new_action._type = AT_stop;
actions.insert(pair<int, Action>(frame, new_action));
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::insert_jump_action
// Access: Private, Static
// Description: Inserts a "jump" action at the indicated frame
// number. When the animation reaches the indicated
// frame number, it will jump to the indicated jump_to
// frame. It will not seem to spend any time at the
// reached frame number.
////////////////////////////////////////////////////////////////////
void AnimControl::
insert_jump_action(Actions &actions, int frame, int jump_to) {
Action new_action;
new_action._type = AT_jump;
new_action._jump_to = jump_to;
actions.insert(pair<int, Action>(frame, new_action));
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::insert_forward_action
// Access: Private, Static
// Description: Inserts a "forward" action at the indicated frame
// number. When the animation hits this action while
// playing in a backward direction, it will stop and
// play in a forward direction instead.
////////////////////////////////////////////////////////////////////
void AnimControl::
insert_forward_action(Actions &actions, int frame) {
Action new_action;
new_action._type = AT_forward;
actions.insert(pair<int, Action>(frame, new_action));
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::insert_backward_action
// Access: Private, Static
// Description: Inserts a "backward" action at the indicated frame
// number. When the animation hits this action while
// playing in a forward direction, it will stop and
// play in a backward direction instead.
////////////////////////////////////////////////////////////////////
void AnimControl::
insert_backward_action(Actions &actions, int frame) {
Action new_action;
new_action._type = AT_backward;
actions.insert(pair<int, Action>(frame, new_action));
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::set_frame
// Access: Private
// Description: Sets the current frame number to the indicated frame,
// and performs any actions on that frame.
////////////////////////////////////////////////////////////////////
void AnimControl::
set_frame(double frame) {
_frame = frame;
int iframe = get_frame();
do_actions_forward(iframe, iframe);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::do_actions_forward
// Access: Private
// Description: Calls each of the actions, in turn, on the timeline
// between the indicated "from" frame and the indicated
// "to" frame, inclusive. If any of the actions
// specifies to stop the animation, the animation is
// stopped, the current frame number is set to the point
// of stopping, no further actions are called, and false
// is returned. Otherwise, true is returned.
////////////////////////////////////////////////////////////////////
bool AnimControl::
do_actions_forward(int from, int to) {
if (to >= from) {
Actions::const_iterator lower = _actions.lower_bound(from);
Actions::const_iterator upper = _actions.lower_bound(to+1);
int sequence_frame = -1;
const Action *sequence_action;
Actions::const_iterator ai;
for (ai = lower; ai != upper; ++ai) {
int frame = (*ai).first;
const Action &action = (*ai).second;
if (sequence_frame != -1 && frame > sequence_frame) {
// We encountered an action that resequenced our frame numbers.
// Now that we've finished evaluating all the other actions that
// occurred in the same frame, evaluate this one action and
// exit.
do_sequence_action(sequence_frame, *sequence_action);
return false;
}
do_action(frame, action, sequence_frame, sequence_action);
}
if (sequence_frame != -1) {
do_sequence_action(sequence_frame, *sequence_action);
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::do_actions_backward
// Access: Private
// Description: Calls each of the actions, in turn, on the timeline
// between the indicated "from" frame and the indicated
// "to" frame, in reverse order. If any of the actions
// specifies to stop the animation, the animation is
// stopped, the current frame number is set to the point
// of stopping, no further actions are called, and false
// is returned. Otherwise, true is returned.
////////////////////////////////////////////////////////////////////
bool AnimControl::
do_actions_backward(int from, int to) {
if (from >= to) {
#if defined(WIN32_VC) && !defined(NO_PCH)
typedef Actions::const_reverse_iterator Action_reverse_iterator;
#else
typedef reverse_iterator<Actions::const_iterator> Action_reverse_iterator;
#endif
Action_reverse_iterator lower(_actions.upper_bound(from));
Action_reverse_iterator upper(_actions.upper_bound(to-1));
int sequence_frame = -1;
const Action *sequence_action;
Action_reverse_iterator ai;
for (ai = lower; ai != upper; ++ai) {
int frame = (*ai).first;
const Action &action = (*ai).second;
if (sequence_frame != -1 && frame < sequence_frame) {
// We encountered an action that resequenced our frame numbers.
// Now that we've finished evaluating all the other actions that
// occurred in the same frame, evaluate this one action and
// exit.
do_sequence_action(sequence_frame, *sequence_action);
return false;
}
do_action(frame, action, sequence_frame, sequence_action);
}
if (sequence_frame != -1) {
do_sequence_action(sequence_frame, *sequence_action);
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::do_action
// Access: Private
// Description: Performs a single action. If the action involves
// some resequencing behavior--stopping, or jumping
// around to a new frame or something--does nothing
// immediately, but instead sets sequence_frame and
// sequence_action to the current frame number and
// action, so they may be executed later (after all the
// other actions this frame have been executed).
////////////////////////////////////////////////////////////////////
void AnimControl::
do_action(int frame, const Action &action,
int &sequence_frame, const Action *&sequence_action) {
switch (action._type) {
case AT_stop:
case AT_jump:
sequence_frame = frame;
sequence_action = &action;
break;
case AT_forward:
// We only see "forward" actions if we're currently playing
// backwards.
if (_play_rate < 0.0f) {
sequence_frame = frame;
sequence_action = &action;
}
break;
case AT_backward:
// We only see "backward" actions if we're currently playing
// forwards.
if (_play_rate > 0.0f) {
sequence_frame = frame;
sequence_action = &action;
}
break;
case AT_event:
throw_event(action._event);
break;
default:
chan_cat.error() << "Invalid action!\n";
abort();
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::do_sequence_action
// Access: Private
// Description: Performs an action that was saved from do_action(),
// above. This action presumably does some mucking
// around with the frame number or something, so we
// needed to do all the other actions associated with
// that frame first.
////////////////////////////////////////////////////////////////////
void AnimControl::
do_sequence_action(int frame, const Action &action) {
switch (action._type) {
case AT_stop:
stop();
break;
case AT_jump:
set_frame(action._jump_to);
break;
case AT_forward:
case AT_backward:
_play_rate = -_play_rate;
set_frame(frame);
break;
case AT_event:
default:
chan_cat.error() << "Invalid sequence action!\n";
abort();
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::Action::output
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void AnimControl::Action::
output(ostream &out) const {
switch (_type) {
case AT_event:
out << "event " << *_event;
break;
case AT_stop:
out << "stop";
break;
case AT_jump:
out << "jump to " << _jump_to;
break;
case AT_forward:
out << "forward";
break;
case AT_backward:
out << "backward";
break;
default:
out << "**error**";
}
animation_activated() {
get_part()->control_activated(this);
}

View File

@ -21,17 +21,11 @@
#include "pandabase.h"
#include "animInterface.h"
#include "animBundle.h"
#include "partGroup.h"
#include "clockObject.h"
#include "typedef.h"
#include "referenceCount.h"
#include "event.h"
#include "pt_Event.h"
#include "cmath.h"
#include <string>
#include "pmap.h"
class PartBundle;
class AnimChannelBase;
@ -44,93 +38,31 @@ class AnimChannelBase;
// animation: whether started, stopped, or looping, and
// the current frame number and play rate.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AnimControl : public ReferenceCount {
class EXPCL_PANDA AnimControl : public ReferenceCount, public AnimInterface {
public:
AnimControl(PartBundle *part, AnimBundle *anim, int channel_index);
PUBLISHED:
~AnimControl();
void play(const CPT_Event &stop_event = NULL);
void play(int from, int to, const CPT_Event &stop_event = NULL);
void loop(bool restart);
void loop(bool restart, int from, int to);
void pingpong(bool restart, int from, int to);
void stop();
void pose(int frame);
void add_event(int frame, const CPT_Event &event);
int remove_event(const string &event_name);
void remove_all_events();
INLINE void set_play_rate(double play_rate);
INLINE double get_play_rate() const;
INLINE double get_frame_rate() const;
INLINE int get_frame() const;
INLINE int get_num_frames() const;
INLINE bool is_playing() const;
virtual ~AnimControl();
PartBundle *get_part() const;
INLINE AnimBundle *get_anim() const;
INLINE int get_channel_index() const;
void output(ostream &out) const;
virtual void output(ostream &out) const;
public:
// The following functions aren't really part of the public
// interface; they're just public so we don't have to declare a
// bunch of friends.
void advance_time(double time);
bool channel_has_changed(AnimChannelBase *channel) const;
void mark_channels();
private:
enum ActionType {
AT_event,
AT_stop,
AT_jump,
AT_forward,
AT_backward,
};
#ifdef WIN32_VC
public:
#endif
class EXPCL_PANDA Action {
public:
ActionType _type;
CPT_Event _event;
int _jump_to;
void output(ostream &out) const;
};
protected:
virtual void animation_activated();
private:
typedef pmultimap<int, Action> Actions;
static void insert_event_action(Actions &actions, int frame, const CPT_Event &event);
static void insert_stop_action(Actions &actions, int frame);
static void insert_jump_action(Actions &actions, int frame, int jump_to);
static void insert_forward_action(Actions &actions, int frame);
static void insert_backward_action(Actions &actions, int frame);
void set_frame(double frame);
bool do_actions_forward(int from, int to);
bool do_actions_backward(int from, int to);
void do_action(int frame, const Action &action,
int &sequence_frame, const Action *&sequence_action);
void do_sequence_action(int frame, const Action &action);
Actions _actions;
Actions _user_actions;
// This is a PT(PartGroup) instead of a PT(PartBundle), just because
// we can't include partBundle.h for circular reasons. But it
// actually keeps a pointer to a PartBundle.
@ -138,17 +70,6 @@ private:
PT(AnimBundle) _anim;
int _channel_index;
double _play_rate;
// We keep a floating-point frame number. This increments fluidly,
// and records honest "between-frame" increments. However, whenever
// we report the current frame number, we just report the integer
// portion.
double _frame;
double _as_of_time;
bool _playing;
// This is the frame number as of the last call to mark_channels().
int _marked_frame;
@ -158,27 +79,16 @@ public:
}
static void init_type() {
ReferenceCount::init_type();
AnimInterface::init_type();
register_type(_type_handle, "AnimControl",
ReferenceCount::get_class_type());
ReferenceCount::get_class_type(),
AnimInterface::get_class_type());
}
private:
static TypeHandle _type_handle;
friend inline ostream &operator << (ostream &, const AnimControl::Action &);
friend class AnimControl::Action;
};
inline ostream &operator << (ostream &out, const AnimControl &ac) {
ac.output(out);
return out;
}
inline ostream &operator << (ostream &out, const AnimControl::Action &action) {
action.output(out);
return out;
}
#include "animControl.I"
#endif

View File

@ -17,60 +17,6 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: AnimControlCollection::set_stop_event
// Access: Public
// Description: Sets the event that will be thrown when the next
// animation that is played eventually comes to a stop.
// Setting this does not affect any stop event that is
// pending from a previously-started animation.
////////////////////////////////////////////////////////////////////
INLINE void AnimControlCollection::
set_stop_event(const CPT_Event &stop_event) {
_stop_event = stop_event;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControlCollection::clear_stop_event
// Access: Public
// Description: Indicates that the next-started animation will not
// throw a stop event when it comes to a stop. This
// does not affect any already-started animations.
////////////////////////////////////////////////////////////////////
INLINE void AnimControlCollection::
clear_stop_event() {
_stop_event = (const Event *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControlCollection::has_stop_event
// Access: Public
// Description: Returns true if a stop event has been established via
// set_stop_event(). If true, this means that
// animations that are to be started in the future will
// throw this event when they stop. However, it does
// not necessarily mean that the currently-playing
// animation will throw this event.
////////////////////////////////////////////////////////////////////
INLINE bool AnimControlCollection::
has_stop_event() const {
return (_stop_event != (const Event *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: AnimControlCollection::get_stop_event
// Access: Public
// Description: Returns the event that has been established via
// set_stop_event(). This is the event that will be
// thrown by animations that are started in the future
// when they stop. However, this may or may not be
// associated with any currently-playing animations.
////////////////////////////////////////////////////////////////////
INLINE CPT_Event AnimControlCollection::
get_stop_event() const {
return _stop_event;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControlCollection::play
// Access: Public
@ -83,7 +29,7 @@ play(const string &anim_name) {
return false;
}
_last_started_control = control;
control->play(_stop_event);
control->play();
return true;
}
@ -99,7 +45,7 @@ play(const string &anim_name, int from, int to) {
return false;
}
_last_started_control = control;
control->play(from, to, _stop_event);
control->play(from, to);
return true;
}

View File

@ -52,11 +52,6 @@ PUBLISHED:
string get_anim_name(int n) const;
void clear_anims();
INLINE void set_stop_event(const CPT_Event &stop_event);
INLINE void clear_stop_event();
INLINE bool has_stop_event() const;
INLINE CPT_Event get_stop_event() const;
// The following functions are convenience functions that vector
// directly into the AnimControl's functionality by anim name.
@ -100,7 +95,6 @@ private:
typedef pmap<string, size_t> ControlsByName;
ControlsByName _controls_by_name;
CPT_Event _stop_event;
AnimControl *_last_started_control;
};

View File

@ -326,21 +326,6 @@ bind_anim(AnimBundle *anim, const string &name,
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::advance_time
// Access: Public
// Description: Calls advance_time() on all AnimControls currently
// in effect.
////////////////////////////////////////////////////////////////////
void PartBundle::
advance_time(double time) {
ChannelBlend::const_iterator cbi;
for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
AnimControl *control = (*cbi).first;
control->advance_time(time);
}
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::update
// Access: Public

View File

@ -123,7 +123,6 @@ public:
// interface; they're just public so we don't have to declare a
// bunch of friends.
void advance_time(double time);
bool update();
bool force_update();
virtual void control_activated(AnimControl *control);

View File

@ -160,10 +160,8 @@ cull_callback(CullTraverser *, CullTraverserData &) {
PStatTimer timer(_joints_pcollector);
double now = ClockObject::get_global_clock()->get_frame_time();
get_bundle()->advance_time(now);
if (char_cat.is_spam()) {
double now = ClockObject::get_global_clock()->get_frame_time();
char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
}
@ -183,10 +181,8 @@ cull_callback(CullTraverser *, CullTraverserData &) {
////////////////////////////////////////////////////////////////////
void Character::
update_to_now() {
double now = ClockObject::get_global_clock()->get_frame_time();
get_bundle()->advance_time(now);
if (char_cat.is_spam()) {
double now = ClockObject::get_global_clock()->get_frame_time();
char_cat.spam() << "Animating " << *this << " at time " << now << "\n";
}

View File

@ -1,7 +1,7 @@
#define LOCAL_LIBS express pandabase
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#define USE_PACKAGES zlib net ssl
#define USE_PACKAGES zlib net openssl
#begin lib_target
#define TARGET downloader

View File

@ -19,7 +19,7 @@
#include "bioPtr.h"
#include "urlSpec.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: BioPtr::Constructor
@ -55,4 +55,4 @@ BioPtr::
}
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include "referenceCount.h"
@ -63,7 +63,7 @@ private:
#include "bioPtr.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -19,7 +19,7 @@
#include "bioStream.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: IBioStream::is_closed
@ -104,4 +104,4 @@ close() {
_buf.close();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "socketStream.h"
#include "bioStreamBuf.h"
@ -94,7 +94,7 @@ private:
#include "bioStream.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -21,7 +21,7 @@
#include "ssl_utils.h"
#include <errno.h>
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#ifndef HAVE_STREAMSIZE
// Some compilers (notably SGI) don't define this for us
@ -275,4 +275,4 @@ write_chars(const char *start, size_t length) {
return length;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include "bioPtr.h"
@ -58,6 +58,6 @@ private:
friend class BioStream;
};
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "bioStreamPtr.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: BioStreamPtr::Destructor
@ -33,4 +33,4 @@ BioStreamPtr::
}
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include "bioStream.h"
@ -52,7 +52,7 @@ private:
#include "bioStreamPtr.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -19,7 +19,7 @@
#include "chunkedStream.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: IChunkedStream::is_closed
@ -48,4 +48,4 @@ close() {
_buf.close_read();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "socketStream.h"
#include "chunkedStreamBuf.h"
@ -55,7 +55,7 @@ private:
#include "chunkedStream.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -21,7 +21,7 @@
#include <ctype.h>
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#ifndef HAVE_STREAMSIZE
// Some compilers (notably SGI) don't define this for us
@ -249,4 +249,4 @@ http_getline(string &str) {
return false;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "httpChannel.h"
#include "bioStreamPtr.h"
@ -60,6 +60,6 @@ private:
friend class IChunkedStream;
};
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -167,7 +167,7 @@ init_libdownloader() {
}
initialized = true;
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
HTTPChannel::init_type();
// We need to define this here, rather than above, to guarantee that
@ -194,5 +194,5 @@ init_libdownloader() {
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->add_system("OpenSSL");
#endif
#endif // HAVE_OPENSSL
}

View File

@ -20,7 +20,7 @@
#include "httpChannel.h"
#include "urlSpec.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
static const char base64_table[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
@ -346,4 +346,4 @@ scan_quoted_or_unquoted_string(string &result, const string &source,
return start;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -25,7 +25,7 @@
// actually use any OpenSSL code, because it is a support module for
// HTTPChannel, which *does* use OpenSSL code.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "referenceCount.h"
#include "httpEnum.h"
@ -81,7 +81,7 @@ protected:
#include "httpAuthorization.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "httpBasicAuthorization.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
const string HTTPBasicAuthorization::_mechanism = "basic";
@ -68,4 +68,4 @@ generate(HTTPEnum::Method, const string &,
return "Basic " + base64_encode(username);
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -25,7 +25,7 @@
// actually use any OpenSSL code, because it is a support module for
// HTTPChannel, which *does* use OpenSSL code.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "httpAuthorization.h"
@ -53,7 +53,7 @@ private:
#include "httpBasicAuthorization.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -27,7 +27,7 @@
#include "clockObject.h"
#include "ramfile.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/x509.h>
#ifdef WIN32_VC
@ -3498,4 +3498,4 @@ operator << (ostream &out, HTTPChannel::State state) {
#endif // NDEBUG
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -26,7 +26,7 @@
// the OpenSSL library to portably handle all of the socket
// communications.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include "httpClient.h"
@ -429,7 +429,7 @@ ostream &operator << (ostream &out, HTTPChannel::State state);
#include "httpChannel.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -28,7 +28,7 @@
#include "httpDigestAuthorization.h"
#include "globPattern.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
#include <openssl/err.h>
@ -1629,4 +1629,4 @@ ssl_msg_callback(int write_p, int version, int content_type,
}
#endif // defined(SSL_097) && !defined(NDEBUG)
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -26,7 +26,7 @@
// the OpenSSL library to portably handle all of the socket
// communications.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include "urlSpec.h"
@ -207,7 +207,7 @@ private:
#include "httpClient.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "httpCookie.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "ctype.h"
#include "httpChannel.h"
@ -218,4 +218,4 @@ parse_cookie_param(const string &param, bool first_param) {
return true;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -26,7 +26,7 @@
// the OpenSSL library to portably handle all of the socket
// communications.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "httpDate.h"
#include "urlSpec.h"
@ -88,6 +88,6 @@ INLINE ostream &operator << (ostream &out, const HTTPCookie &cookie);
#include "httpCookie.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "httpDigestAuthorization.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/ssl.h>
#include <openssl/md5.h>
@ -371,4 +371,4 @@ operator << (ostream &out, HTTPDigestAuthorization::Qop qop) {
return out;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -25,7 +25,7 @@
// actually use any OpenSSL code, because it is a support module for
// HTTPChannel, which *does* use OpenSSL code.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "httpAuthorization.h"
@ -96,7 +96,7 @@ ostream &operator << (ostream &out, HTTPDigestAuthorization::Qop qop);
#include "httpDigestAuthorization.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "httpEnum.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: HTTPEnum::Method::output operator
@ -63,4 +63,4 @@ operator << (ostream &out, HTTPEnum::Method method) {
return out;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -26,7 +26,7 @@
// the OpenSSL library to portably handle all of the socket
// communications.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Class : HTTPEnum
@ -57,7 +57,7 @@ PUBLISHED:
ostream &operator << (ostream &out, HTTPEnum::Method method);
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -19,7 +19,7 @@
#include "identityStream.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: IIdentityStream::is_closed
@ -49,4 +49,4 @@ close() {
_buf.close_read();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "socketStream.h"
#include "identityStreamBuf.h"
@ -62,7 +62,7 @@ private:
#include "identityStream.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -19,7 +19,7 @@
#include "identityStreamBuf.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#ifndef HAVE_STREAMSIZE
// Some compilers (notably SGI) don't define this for us
@ -180,4 +180,4 @@ read_chars(char *start, size_t length) {
return read_count;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "httpChannel.h"
#include "bioStreamPtr.h"
@ -58,6 +58,6 @@ private:
friend class IIdentityStream;
};
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "pandabase.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "config_downloader.h"
#include "patcher.h"
@ -89,4 +89,4 @@ run() {
return _patchfile->run();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -21,7 +21,7 @@
#include "pandabase.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "filename.h"
#include "buffer.h"
@ -50,6 +50,6 @@ private:
#include "patcher.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -20,7 +20,7 @@
#include "datagram.h"
#include "datagramIterator.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: SSReader::Destructor
@ -209,4 +209,4 @@ send_datagram(const Datagram &dg) {
return !is_closed();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -29,7 +29,7 @@
// available, since the only current use for it is to implement
// OpenSSL-defined constructs (like ISocketStream).
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Class : SSReader
@ -168,7 +168,7 @@ PUBLISHED:
#include "socketStream.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -19,7 +19,7 @@
#include "ssl_utils.h"
#include "config_downloader.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#ifdef REPORT_OPENSSL_ERRORS
#include <openssl/err.h>
@ -53,4 +53,4 @@ void notify_ssl_errors() {
#endif // REPORT_OPENSSL_ERRORS
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,14 +22,14 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#define OPENSSL_NO_KRB5
#include <openssl/ssl.h>
EXPCL_PANDAEXPRESS void notify_ssl_errors();
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -4,7 +4,7 @@
#begin bin_target
#define TARGET apply_patch
#define BUILD_TARGET $[HAVE_SSL]
#define BUILD_TARGET $[HAVE_OPENSSL]
#define SOURCES \
apply_patch.cxx
@ -15,7 +15,7 @@
#begin bin_target
#define TARGET build_patch
#define BUILD_TARGET $[HAVE_SSL]
#define BUILD_TARGET $[HAVE_OPENSSL]
#define SOURCES \
build_patch.cxx
@ -24,7 +24,7 @@
#begin bin_target
#define TARGET show_ddb
#define BUILD_TARGET $[HAVE_SSL]
#define BUILD_TARGET $[HAVE_OPENSSL]
#define SOURCES \
show_ddb.cxx
@ -53,8 +53,8 @@
#begin bin_target
#define TARGET check_md5
#define BUILD_TARGET $[HAVE_SSL]
#define USE_PACKAGES $[USE_PACKAGES] ssl
#define BUILD_TARGET $[HAVE_OPENSSL]
#define USE_PACKAGES $[USE_PACKAGES] openssl
#define SOURCES \
check_md5.cxx
@ -91,8 +91,8 @@
#begin bin_target
#define TARGET pencrypt
#define BUILD_TARGET $[HAVE_SSL]
#define USE_PACKAGES $[USE_PACKAGES] ssl
#define BUILD_TARGET $[HAVE_OPENSSL]
#define USE_PACKAGES $[USE_PACKAGES] openssl
#define SOURCES \
pencrypt.cxx
@ -101,8 +101,8 @@
#begin bin_target
#define TARGET pdecrypt
#define BUILD_TARGET $[HAVE_SSL]
#define USE_PACKAGES $[USE_PACKAGES] ssl
#define BUILD_TARGET $[HAVE_OPENSSL]
#define USE_PACKAGES $[USE_PACKAGES] openssl
#define SOURCES \
pdecrypt.cxx

View File

@ -4,7 +4,7 @@
#begin lib_target
#define TARGET express
#define USE_PACKAGES nspr net zlib ssl
#define USE_PACKAGES nspr net zlib openssl
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx

View File

@ -18,7 +18,7 @@
#include "encryptStream.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: encrypt_string
// Access: Published
@ -66,4 +66,4 @@ decrypt_string(const string &source, const string &password) {
return output.str();
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "encryptStreamBuf.h"
@ -92,7 +92,7 @@ END_PUBLISH
#include "encryptStream.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -21,7 +21,7 @@
#include "streamReader.h"
#include "streamWriter.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
@ -477,4 +477,4 @@ write_chars(const char *start, size_t length) {
}
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
// This module is not compiled if OpenSSL is not available.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/evp.h>
@ -84,6 +84,6 @@ private:
#include "encryptStreamBuf.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -202,7 +202,7 @@ read_stream(StreamReader &source) {
_hv[3] = source.get_uint32();
}
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: HashVal::hash_ramfile
// Access: Published
@ -228,7 +228,7 @@ INLINE void HashVal::
hash_string(const string &data) {
return hash_buffer(data.data(), data.length());
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: HashVal::tohex

View File

@ -21,9 +21,9 @@
#include <ctype.h>
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
@ -164,7 +164,7 @@ set_from_hex(const string &text) {
return !strm.fail();
}
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
////////////////////////////////////////////////////////////////////
// Function: HashVal::hash_file
// Access: Published
@ -234,7 +234,7 @@ hash_buffer(const char *buffer, int length) {
_hv[3] = (md[12] << 24) | (md[13] << 16) | (md[14] << 8) | (md[15]);
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
////////////////////////////////////////////////////////////////////

View File

@ -66,12 +66,12 @@ PUBLISHED:
INLINE void write_stream(StreamWriter &destination) const;
INLINE void read_stream(StreamReader &source);
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
bool hash_file(const Filename &filename);
INLINE void hash_ramfile(const Ramfile &ramfile);
INLINE void hash_string(const string &data);
void hash_buffer(const char *buffer, int length);
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
private:
static void encode_hex(PN_uint32 val, char *buffer);

View File

@ -92,13 +92,13 @@ get_scale_factor() const {
////////////////////////////////////////////////////////////////////
INLINE void Multifile::
set_encryption_flag(bool flag) {
#ifndef HAVE_SSL
#ifndef HAVE_OPENSSL
if (flag) {
express_cat.warning()
<< "OpenSSL not compiled in; cannot generated encrypted multifiles.\n";
flag = false;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
_encryption_flag = flag;
}

View File

@ -846,12 +846,12 @@ open_read_subfile(int index) {
subfile->_data_start + (streampos)subfile->_data_length);
if ((subfile->_flags & SF_encrypted) != 0) {
#ifndef HAVE_SSL
#ifndef HAVE_OPENSSL
express_cat.error()
<< "OpenSSL not compiled in; cannot read encrypted multifiles.\n";
delete stream;
return NULL;
#else // HAVE_SSL
#else // HAVE_OPENSSL
// The subfile is encrypted. So actually, return an
// IDecryptStream that wraps around the ISubStream.
IDecryptStream *wrapper =
@ -869,7 +869,7 @@ open_read_subfile(int index) {
delete stream;
return NULL;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
}
if ((subfile->_flags & SF_compressed) != 0) {
@ -1182,11 +1182,11 @@ add_new_subfile(Subfile *subfile, int compression_level) {
#endif // HAVE_ZLIB
}
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
if (_encryption_flag) {
subfile->_flags |= SF_encrypted;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
if (_next_index != (streampos)0) {
// If we're adding a Subfile to an already-existing Multifile, we
@ -1566,7 +1566,7 @@ write_data(ostream &write, istream *read, streampos fpos,
ostream *putter = &write;
bool delete_putter = false;
#ifndef HAVE_SSL
#ifndef HAVE_OPENSSL
// Without OpenSSL, we can't support encryption. The flag had
// better not be set.
nassertr((_flags & SF_encrypted) == 0, fpos);

View File

@ -20,7 +20,7 @@
// The functions defined within this file rely on algorithms defined
// within OpenSSL.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include <openssl/evp.h>
@ -75,5 +75,5 @@ password_hash(const string &password, const string &salt,
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -23,7 +23,7 @@
// The functions defined within this file rely on algorithms defined
// within OpenSSL.
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
BEGIN_PUBLISH
@ -32,6 +32,6 @@ string password_hash(const string &password, const string &salt,
END_PUBLISH
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -18,7 +18,7 @@
#include "pandabase.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "config_express.h"
#include "error_utils.h"
@ -981,4 +981,4 @@ build(Filename file_orig, Filename file_new, Filename patch_name) {
return true;
}
#endif // HAVE_SSL
#endif // HAVE_OPENSSL

View File

@ -20,7 +20,7 @@
#include "pandabase.h"
#ifdef HAVE_SSL
#ifdef HAVE_OPENSSL
#include "typedef.h"
#include "notify.h"
@ -136,6 +136,6 @@ protected:
#include "patchfile.I"
#endif // HAVE_SSL
#endif // HAVE_OPENSSL
#endif

View File

@ -5700,6 +5700,9 @@ upload_texture_image(CLP(TextureContext) *gtc,
} else {
// We can reload the image over the previous image, possibly
// saving on texture memory fragmentation.
#ifdef DO_PSTATS
_data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type));
#endif
switch (target) {
case GL_TEXTURE_1D:
GLP(TexSubImage1D)(target, 0, 0, width,

View File

@ -57,7 +57,8 @@
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexSlider.I vertexSlider.h \
vertexTransform.I vertexTransform.h
vertexTransform.I vertexTransform.h \
videoTexture.I videoTexture.h
#define INCLUDED_SOURCES \
boundedObject.cxx \
@ -104,7 +105,8 @@
userVertexTransform.cxx \
vertexBufferContext.cxx \
vertexSlider.cxx \
vertexTransform.cxx
vertexTransform.cxx \
videoTexture.cxx
#define INSTALL_HEADERS \
boundedObject.I boundedObject.h \
@ -156,7 +158,8 @@
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexSlider.I vertexSlider.h \
vertexTransform.I vertexTransform.h
vertexTransform.I vertexTransform.h \
videoTexture.I videoTexture.h
#define IGATESCAN all

View File

@ -50,6 +50,7 @@
#include "userVertexTransform.h"
#include "vertexTransform.h"
#include "vertexSlider.h"
#include "videoTexture.h"
#include "geomContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
@ -187,14 +188,6 @@ ConfigVariableEnum<AutoTextureScale> textures_square
"a square aspect ratio when they are loaded from disk. Set this "
"to 'none', 'down', or 'up'. See textures-power-2."));
ConfigVariableString fake_texture_image
("fake-texture-image", "",
PRC_DESC("Set this to enable a speedy-load mode in which you don't care "
"what the world looks like, you just want it to load in minimal "
"time. This causes all texture loads via the TexturePool to use "
"the same texture file, which will presumably only be loaded "
"once."));
ConfigVariableInt geom_cache_size
("geom-cache-size", 5000,
PRC_DESC("Specifies the maximum number of entries in the cache "
@ -264,6 +257,7 @@ ConfigureFn(config_gobj) {
UserVertexTransform::init_type();
VertexTransform::init_type();
VertexSlider::init_type();
VideoTexture::init_type();
InternalName::init_type();
//Registration of writeable object's creation

View File

@ -61,7 +61,6 @@ extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips;
extern EXPCL_PANDA ConfigVariableEnum<BamTextureMode> bam_texture_mode;
extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_power_2;
extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_square;
extern EXPCL_PANDA ConfigVariableString fake_texture_image;
extern EXPCL_PANDA ConfigVariableInt geom_cache_size;
extern EXPCL_PANDA ConfigVariableInt geom_cache_min_frames;

View File

@ -26,3 +26,4 @@
#include "vertexBufferContext.cxx"
#include "vertexSlider.cxx"
#include "vertexTransform.cxx"
#include "videoTexture.cxx"

View File

@ -91,7 +91,7 @@ parse_upto(string &result, string pattern, bool include) {
GlobPattern endpat(pattern);
int start = _parse;
int last = _parse;
while (_parse < _text.size()) {
while (_parse < (int)_text.size()) {
string t;
parse_line(t, true, true);
if (endpat.matches(t)) break;

View File

@ -411,36 +411,18 @@ uses_mipmaps() const {
}
////////////////////////////////////////////////////////////////////
// Function: Texture::has_ram_image
// Function: Texture::might_have_ram_image
// Access: Published
// Description: Returns true if the Texture has its image contents
// available in main RAM, false if it exists only in
// texture memory or in the prepared GSG context.
//
// Note that this has nothing to do with whether
// get_ram_image() will fail or not. Even if
// has_ram_image() returns false, get_ram_image() may
// still return a valid RAM image, because
// get_ram_image() will automatically load the texture
// from disk if necessary. The only thing
// has_ram_image() tells you is whether the texture is
// available right now without hitting the disk first.
//
// Note also that if an application uses only one GSG,
// it may appear that has_ram_image() returns true if
// the texture has not yet been loaded by the GSG, but
// this correlation is not true in general and should
// not be depended on. Specifically, if an application
// ever uses multiple GSG's in its lifetime (for
// instance, by opening more than one window, or by
// closing its window and opening another one later),
// then has_ram_image() may well return false on
// textures that have never been loaded on the current
// GSG.
// Description: Returns true if the texture's image contents are
// currently available in main RAM, or there is reason
// to believe it can be loaded on demand. That is, this
// function returns a "best guess" as to whether
// get_ram_image() will succeed without actually calling
// it first.
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
has_ram_image() const {
return !_image.empty();
might_have_ram_image() const {
return (has_ram_image() || has_filename());
}
////////////////////////////////////////////////////////////////////
@ -479,21 +461,6 @@ get_expected_ram_page_size() const {
return (size_t)(_x_size * _y_size * _num_components * _component_width);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::might_have_ram_image
// Access: Published
// Description: Returns true if the texture's image contents are
// currently available in main RAM, or there is reason
// to believe it can be loaded on demand. That is, this
// function returns a "best guess" as to whether
// get_ram_image() will succeed without actually calling
// it first.
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
might_have_ram_image() const {
return (has_ram_image() || has_filename());
}
////////////////////////////////////////////////////////////////////
// Function: Texture::set_keep_ram_image
// Access: Published
@ -514,19 +481,6 @@ set_keep_ram_image(bool keep_ram_image) {
_keep_ram_image = keep_ram_image;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_keep_ram_image
// Access: Published
// Description: Returns the flag that indicates whether this Texture
// is eligible to have its main RAM copy of the texture
// memory dumped when the texture is prepared for
// rendering. See set_keep_ram_image().
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
get_keep_ram_image() const {
return _keep_ram_image;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::set_filename
// Access: Published
@ -700,6 +654,17 @@ set_loaded_from_disk() {
_loaded_from_disk = true;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_loaded_from_disk
// Access: Published
// Description: Returns the flag that indicates the texture has been
// loaded from a disk file. See set_loaded_from_disk().
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
get_loaded_from_disk() const {
return _loaded_from_disk;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_match_framebuffer_format
// Access: Public

View File

@ -71,6 +71,44 @@ Texture(const string &name) :
_loaded_from_disk = false;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::Copy Constructor
// Access: Protected
// Description: Use Texture::make_copy() to make a duplicate copy of
// an existing Texture.
////////////////////////////////////////////////////////////////////
Texture::
Texture(const Texture &copy) :
Namable(copy),
_filename(copy._filename),
_alpha_filename(copy._alpha_filename),
_fullpath(copy._fullpath),
_alpha_fullpath(copy._alpha_fullpath),
_primary_file_num_channels(copy._primary_file_num_channels),
_alpha_file_channel(copy._alpha_file_channel),
_x_size(copy._x_size),
_y_size(copy._y_size),
_z_size(copy._z_size),
_num_components(copy._num_components),
_component_width(copy._component_width),
_texture_type(copy._texture_type),
_format(copy._format),
_component_type(copy._component_type),
_loaded_from_disk(copy._loaded_from_disk),
_wrap_u(copy._wrap_u),
_wrap_v(copy._wrap_v),
_wrap_w(copy._wrap_w),
_minfilter(copy._minfilter),
_magfilter(copy._magfilter),
_anisotropic_degree(copy._anisotropic_degree),
_keep_ram_image(copy._keep_ram_image),
_border_color(copy._border_color),
_match_framebuffer_format(copy._match_framebuffer_format),
_all_dirty_flags(0),
_image(copy._image)
{
}
////////////////////////////////////////////////////////////////////
// Function: Texture::Destructor
// Access: Published, Virtual
@ -81,6 +119,24 @@ Texture::
release_all();
}
////////////////////////////////////////////////////////////////////
// Function: Texture::make_copy
// Access: Published, Virtual
// Description: Returns a new copy of the same Texture. This copy,
// if applied to geometry, will be copied into texture
// as a separate texture from the original, so it will
// be duplicated in texture memory (and may be
// independently modified if desired).
//
// If the Texture is an AviTexture, the resulting
// duplicate may be animated independently of the
// original.
////////////////////////////////////////////////////////////////////
PT(Texture) Texture::
make_copy() {
return new Texture(*this);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::setup_texture
// Access: Published
@ -221,7 +277,7 @@ generate_normalization_cube_map(int size) {
////////////////////////////////////////////////////////////////////
// Function: Texture::read
// Access: Published
// Access: Published, Virtual
// Description: Reads the texture from the indicated filename. If
// num_channels is not 0, it specifies the number of
// components to downgrade the image to if it is greater
@ -262,7 +318,7 @@ read(const Filename &fullpath, int z, int primary_file_num_channels) {
////////////////////////////////////////////////////////////////////
// Function: Texture::read
// Access: Published
// Access: Published, Virtual
// Description: Combine a 3-component image with a grayscale image
// to get a 4-component image
//
@ -477,7 +533,7 @@ write_pages(const HashFilename &fullpath_template) {
////////////////////////////////////////////////////////////////////
// Function: Texture::load
// Access: Published
// Access: Published, Virtual
// Description: Fills the texture system RAM data from the
// already-read PNMImage.
//
@ -496,85 +552,21 @@ write_pages(const HashFilename &fullpath_template) {
////////////////////////////////////////////////////////////////////
bool Texture::
load(const PNMImage &pnmimage, int z) {
if (z >= _z_size) {
// If we're loading a page past _z_size, treat it as an implicit
// request to enlarge _z_size. However, this is only legal if
// this is, in fact, a 3-d texture (cube maps always have z_size
// 6, and other types have z_size 1).
nassertr(_texture_type == Texture::TT_3d_texture, false);
_z_size = z + 1;
// Increase the size of the data buffer to make room for the new
// texture level.
size_t new_size = get_expected_ram_image_size();
if (!_image.is_null() && new_size > _image.size()) {
_image.insert(_image.end(), new_size - _image.size(), 0);
nassertr(_image.size() == new_size, false);
}
if (!reconsider_z_size(z)) {
return false;
}
nassertr(z >= 0 && z < _z_size, false);
int num_components = pnmimage.get_num_channels();
ComponentType component_type = T_unsigned_byte;
xelval maxval = pnmimage.get_maxval();
if (maxval > 255) {
component_type = T_unsigned_short;
}
if (!_loaded_from_disk || num_components != _num_components) {
// Come up with a default format based on the number of channels.
// But only do this the first time the file is loaded, or if the
// number of channels in the image changes on subsequent loads.
switch (pnmimage.get_color_type()) {
case PNMImage::CT_grayscale:
_format = F_luminance;
break;
case PNMImage::CT_two_channel:
_format = F_luminance_alpha;
break;
case PNMImage::CT_color:
_format = F_rgb;
break;
case PNMImage::CT_four_channel:
_format = F_rgba;
break;
default:
// Eh?
nassertr(false, false);
_format = F_rgb;
}
}
if (!_loaded_from_disk) {
#ifndef NDEBUG
if (_texture_type == TT_1d_texture) {
nassertr(pnmimage.get_y_size() == 1, false);
} else if (_texture_type == TT_cube_map) {
nassertr(pnmimage.get_x_size() == pnmimage.get_y_size(), false);
}
#endif
_x_size = pnmimage.get_x_size();
_y_size = pnmimage.get_y_size();
_num_components = num_components;
set_component_type(component_type);
} else {
if (_x_size != pnmimage.get_x_size() ||
_y_size != pnmimage.get_y_size() ||
_num_components != num_components ||
_component_type != component_type) {
gobj_cat.error()
<< "Texture properties have changed for texture " << get_name()
<< " level " << z << ".\n";
return false;
}
if (!reconsider_image_properties(pnmimage.get_x_size(), pnmimage.get_y_size(),
pnmimage.get_num_channels(), component_type,
z)) {
return false;
}
_loaded_from_disk = true;
@ -856,6 +848,39 @@ set_border_color(const Colorf &color) {
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::has_ram_image
// Access: Published, Virtual
// Description: Returns true if the Texture has its image contents
// available in main RAM, false if it exists only in
// texture memory or in the prepared GSG context.
//
// Note that this has nothing to do with whether
// get_ram_image() will fail or not. Even if
// has_ram_image() returns false, get_ram_image() may
// still return a valid RAM image, because
// get_ram_image() will automatically load the texture
// from disk if necessary. The only thing
// has_ram_image() tells you is whether the texture is
// available right now without hitting the disk first.
//
// Note also that if an application uses only one GSG,
// it may appear that has_ram_image() returns true if
// the texture has not yet been loaded by the GSG, but
// this correlation is not true in general and should
// not be depended on. Specifically, if an application
// ever uses multiple GSG's in its lifetime (for
// instance, by opening more than one window, or by
// closing its window and opening another one later),
// then has_ram_image() may well return false on
// textures that have never been loaded on the current
// GSG.
////////////////////////////////////////////////////////////////////
bool Texture::
has_ram_image() const {
return !_image.empty();
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_ram_image
// Access: Published
@ -886,19 +911,8 @@ set_border_color(const Colorf &color) {
////////////////////////////////////////////////////////////////////
CPTA_uchar Texture::
get_ram_image() {
if (_loaded_from_disk && !has_ram_image() && has_filename() &&
(_texture_type == TT_1d_texture || _texture_type == TT_2d_texture)) {
// Now we have to reload the texture image.
gobj_cat.info()
<< "Reloading texture " << get_name() << "\n";
make_ram_image();
if (has_alpha_fullpath()) {
read(get_fullpath(), get_alpha_fullpath(),
0, _primary_file_num_channels, _alpha_file_channel);
} else {
read(get_fullpath(), 0, _primary_file_num_channels);
}
if (_loaded_from_disk && !has_ram_image() && has_filename()) {
reload_ram_image();
}
return _image;
@ -914,7 +928,7 @@ get_ram_image() {
////////////////////////////////////////////////////////////////////
PTA_uchar Texture::
modify_ram_image() {
if (!has_ram_image()) {
if (_image.empty()) {
make_ram_image();
}
@ -968,6 +982,19 @@ clear_ram_image() {
_image.clear();
}
////////////////////////////////////////////////////////////////////
// Function: Texture::get_keep_ram_image
// Access: Published, Virtual
// Description: Returns the flag that indicates whether this Texture
// is eligible to have its main RAM copy of the texture
// memory dumped when the texture is prepared for
// rendering. See set_keep_ram_image().
////////////////////////////////////////////////////////////////////
bool Texture::
get_keep_ram_image() const {
return _keep_ram_image;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::prepare
// Access: Published
@ -1218,6 +1245,38 @@ mark_dirty(int flags_to_set) {
_all_dirty_flags |= flags_to_set;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::has_cull_callback
// Access: Public, Virtual
// Description: Should be overridden by derived classes to return
// true if cull_callback() has been defined. Otherwise,
// returns false to indicate cull_callback() does not
// need to be called for this node during the cull
// traversal.
////////////////////////////////////////////////////////////////////
bool Texture::
has_cull_callback() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::cull_callback
// Access: Public, Virtual
// Description: If has_cull_callback() returns true, this function
// will be called during the cull traversal to perform
// any additional operations that should be performed at
// cull time.
//
// This is called each time the Texture is discovered
// applied to a Geom in the traversal. It should return
// true if the Geom is visible, false if it should be
// omitted.
////////////////////////////////////////////////////////////////////
bool Texture::
cull_callback(CullTraverser *, const CullTraverserData &) const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::string_wrap_mode
// Access: Public
@ -1271,6 +1330,41 @@ string_filter_type(const string &string) {
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::reconsider_dirty
// Access: Protected, Virtual
// Description: Called by TextureContext to give the Texture a chance
// to mark itself dirty before rendering, if necessary.
////////////////////////////////////////////////////////////////////
void Texture::
reconsider_dirty() {
}
////////////////////////////////////////////////////////////////////
// Function: Texture::reload_ram_image
// Access: Protected, Virtual
// Description: Called when the Texture image is required but the ram
// image is not available, this will reload it from disk
// or otherwise do whatever is required to make it
// available, if possible.
////////////////////////////////////////////////////////////////////
void Texture::
reload_ram_image() {
if (_texture_type == TT_1d_texture || _texture_type == TT_2d_texture) {
gobj_cat.info()
<< "Reloading texture " << get_name() << "\n";
make_ram_image();
if (has_alpha_fullpath()) {
read(get_fullpath(), get_alpha_fullpath(),
0, _primary_file_num_channels, _alpha_file_channel);
} else {
read(get_fullpath(), 0, _primary_file_num_channels);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::up_to_power_2
// Access: Protected, Static
@ -1301,6 +1395,102 @@ down_to_power_2(int value) {
return x;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::reconsider_z_size
// Access: Protected
// Description: Considers whether the z_size should automatically be
// adjusted when the user loads a new page. Returns
// true if the z size is valid, false otherwise.
////////////////////////////////////////////////////////////////////
bool Texture::
reconsider_z_size(int z) {
if (z >= _z_size) {
// If we're loading a page past _z_size, treat it as an implicit
// request to enlarge _z_size. However, this is only legal if
// this is, in fact, a 3-d texture (cube maps always have z_size
// 6, and other types have z_size 1).
nassertr(_texture_type == Texture::TT_3d_texture, false);
_z_size = z + 1;
// Increase the size of the data buffer to make room for the new
// texture level.
size_t new_size = get_expected_ram_image_size();
if (!_image.is_null() && new_size > _image.size()) {
_image.insert(_image.end(), new_size - _image.size(), 0);
nassertr(_image.size() == new_size, false);
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::reconsider_image_properties
// Access: Protected
// Description: Resets the internal Texture properties when a new
// image file is loaded. Returns true if the new image
// is valid, false otherwise.
////////////////////////////////////////////////////////////////////
bool Texture::
reconsider_image_properties(int x_size, int y_size, int num_components,
Texture::ComponentType component_type, int z) {
if (!_loaded_from_disk || num_components != _num_components) {
// Come up with a default format based on the number of channels.
// But only do this the first time the file is loaded, or if the
// number of channels in the image changes on subsequent loads.
switch (num_components) {
case 1:
_format = F_luminance;
break;
case 2:
_format = F_luminance_alpha;
break;
case 3:
_format = F_rgb;
break;
case 4:
_format = F_rgba;
break;
default:
// Eh?
nassertr(false, false);
_format = F_rgb;
}
}
if (!_loaded_from_disk) {
#ifndef NDEBUG
if (_texture_type == TT_1d_texture) {
nassertr(y_size == 1, false);
} else if (_texture_type == TT_cube_map) {
nassertr(x_size == y_size, false);
}
#endif
_x_size = x_size;
_y_size = y_size;
_num_components = num_components;
set_component_type(component_type);
} else {
if (_x_size != x_size ||
_y_size != y_size ||
_num_components != num_components ||
_component_type != component_type) {
gobj_cat.error()
<< "Texture properties have changed for texture " << get_name()
<< " level " << z << ".\n";
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::clear_prepared
// Access: Private
@ -1323,6 +1513,7 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
}
}
////////////////////////////////////////////////////////////////////
// Function: Texture::consider_rescale
// Access: Private
@ -1444,7 +1635,7 @@ make_Texture(const FactoryParams &params) {
if (has_rawdata) {
// If the raw image data is included, then just create a Texture
// and don't load from the file.
me = new Texture;
me = new Texture("");
} else {
if (filename.empty()) {
@ -1473,7 +1664,7 @@ make_Texture(const FactoryParams &params) {
// Oops, we couldn't load the texture; we'll just return NULL.
// But we do need a dummy texture to read in and ignore all of the
// attributes.
PT(Texture) dummy = new Texture;
PT(Texture) dummy = new Texture("");
dummy->fillin(scan, manager, has_rawdata);
} else {

View File

@ -32,6 +32,8 @@ class TextureContext;
class FactoryParams;
class PreparedGraphicsObjects;
class HashFilename;
class CullTraverser;
class CullTraverserData;
////////////////////////////////////////////////////////////////////
// Class : Texture
@ -133,8 +135,13 @@ PUBLISHED:
PUBLISHED:
Texture(const string &name = string());
protected:
Texture(const Texture &copy);
PUBLISHED:
virtual ~Texture();
virtual PT(Texture) make_copy();
void setup_texture(TextureType texture_type,
int x_size, int y_size, int z_size,
ComponentType component_type, Format format);
@ -154,17 +161,17 @@ PUBLISHED:
void generate_normalization_cube_map(int size);
bool read(const Filename &fullpath, int z = 0,
int primary_file_num_channels = 0);
bool read(const Filename &fullpath, const Filename &alpha_fullpath,
int z = 0,
int primary_file_num_channels = 0, int alpha_file_channel = 0);
virtual bool read(const Filename &fullpath, int z = 0,
int primary_file_num_channels = 0);
virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath,
int z = 0,
int primary_file_num_channels = 0, int alpha_file_channel = 0);
bool write(const Filename &fullpath, int z = 0) const;
bool read_pages(const HashFilename &fullpath_template, int z_size = 0);
bool write_pages(const HashFilename &fullpath_template);
bool load(const PNMImage &pnmimage, int z = 0);
virtual bool load(const PNMImage &pnmimage, int z = 0);
bool store(PNMImage &pnmimage, int z = 0) const;
INLINE bool has_filename() const;
@ -203,7 +210,7 @@ PUBLISHED:
INLINE Colorf get_border_color() const;
INLINE bool uses_mipmaps() const;
INLINE bool has_ram_image() const;
virtual bool has_ram_image() const;
INLINE bool might_have_ram_image() const;
INLINE size_t get_ram_image_size() const;
INLINE size_t get_expected_ram_image_size() const;
@ -214,7 +221,7 @@ PUBLISHED:
void set_ram_image(PTA_uchar image);
void clear_ram_image();
INLINE void set_keep_ram_image(bool keep_ram_image);
INLINE bool get_keep_ram_image() const;
virtual bool get_keep_ram_image() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
bool release(PreparedGraphicsObjects *prepared_objects);
@ -240,6 +247,7 @@ PUBLISHED:
void set_format(Format format);
void set_component_type(ComponentType component_type);
INLINE void set_loaded_from_disk();
INLINE bool get_loaded_from_disk() const;
public:
INLINE bool get_match_framebuffer_format() const;
@ -263,16 +271,25 @@ public:
void mark_dirty(int flags_to_set);
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
static WrapMode string_wrap_mode(const string &string);
static FilterType string_filter_type(const string &string);
protected:
virtual void reconsider_dirty();
virtual void reload_ram_image();
static int up_to_power_2(int value);
static int down_to_power_2(int value);
bool reconsider_z_size(int z);
bool reconsider_image_properties(int x_size, int y_size, int num_components,
ComponentType component_type, int z);
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
void consider_rescale(PNMImage &pnmimage);
void consider_downgrade(PNMImage &pnmimage, int num_channels);
@ -283,7 +300,7 @@ private:
INLINE double get_unsigned_byte(int &index) const;
INLINE double get_unsigned_short(int &index) const;
private:
protected:
Filename _filename;
Filename _alpha_filename;
Filename _fullpath;

View File

@ -86,6 +86,7 @@ clear_dirty_flags(int flags_to_clear) {
////////////////////////////////////////////////////////////////////
INLINE int TextureContext::
get_dirty_flags() const {
_texture->reconsider_dirty();
return _dirty_flags;
}

View File

@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////
INLINE bool TexturePool::
has_texture(const string &filename) {
return get_ptr()->ns_has_texture(filename);
return get_global_ptr()->ns_has_texture(filename);
}
////////////////////////////////////////////////////////////////////
@ -54,7 +54,7 @@ verify_texture(const string &filename) {
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_texture(const string &filename, int primary_file_num_channels) {
return get_ptr()->ns_load_texture(filename, primary_file_num_channels);
return get_global_ptr()->ns_load_texture(filename, primary_file_num_channels);
}
////////////////////////////////////////////////////////////////////
@ -69,7 +69,7 @@ load_texture(const string &filename, int primary_file_num_channels) {
INLINE Texture *TexturePool::
load_texture(const string &filename, const string &alpha_filename,
int primary_file_num_channels, int alpha_file_channel) {
return get_ptr()->ns_load_texture(filename, alpha_filename,
return get_global_ptr()->ns_load_texture(filename, alpha_filename,
primary_file_num_channels,
alpha_file_channel);
}
@ -85,7 +85,7 @@ load_texture(const string &filename, const string &alpha_filename,
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_3d_texture(const string &filename_template) {
return get_ptr()->ns_load_3d_texture(filename_template);
return get_global_ptr()->ns_load_3d_texture(filename_template);
}
////////////////////////////////////////////////////////////////////
@ -99,7 +99,7 @@ load_3d_texture(const string &filename_template) {
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_cube_map(const string &filename_template) {
return get_ptr()->ns_load_cube_map(filename_template);
return get_global_ptr()->ns_load_cube_map(filename_template);
}
////////////////////////////////////////////////////////////////////
@ -115,7 +115,7 @@ load_cube_map(const string &filename_template) {
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
get_normalization_cube_map(int size) {
return get_ptr()->ns_get_normalization_cube_map(size);
return get_global_ptr()->ns_get_normalization_cube_map(size);
}
////////////////////////////////////////////////////////////////////
@ -129,7 +129,7 @@ get_normalization_cube_map(int size) {
////////////////////////////////////////////////////////////////////
INLINE void TexturePool::
add_texture(Texture *texture) {
get_ptr()->ns_add_texture(texture);
get_global_ptr()->ns_add_texture(texture);
}
////////////////////////////////////////////////////////////////////
@ -147,7 +147,7 @@ add_texture(Texture *texture) {
////////////////////////////////////////////////////////////////////
INLINE void TexturePool::
release_texture(Texture *texture) {
get_ptr()->ns_release_texture(texture);
get_global_ptr()->ns_release_texture(texture);
}
////////////////////////////////////////////////////////////////////
@ -158,7 +158,7 @@ release_texture(Texture *texture) {
////////////////////////////////////////////////////////////////////
INLINE void TexturePool::
release_all_textures() {
get_ptr()->ns_release_all_textures();
get_global_ptr()->ns_release_all_textures();
}
////////////////////////////////////////////////////////////////////
@ -171,7 +171,7 @@ release_all_textures() {
////////////////////////////////////////////////////////////////////
INLINE int TexturePool::
garbage_collect() {
return get_ptr()->ns_garbage_collect();
return get_global_ptr()->ns_garbage_collect();
}
////////////////////////////////////////////////////////////////////
@ -182,7 +182,7 @@ garbage_collect() {
////////////////////////////////////////////////////////////////////
INLINE void TexturePool::
list_contents(ostream &out) {
get_ptr()->ns_list_contents(out);
get_global_ptr()->ns_list_contents(out);
}
////////////////////////////////////////////////////////////////////
@ -193,7 +193,7 @@ list_contents(ostream &out) {
////////////////////////////////////////////////////////////////////
INLINE void TexturePool::
set_fake_texture_image(const string &filename) {
get_ptr()->_fake_texture_image = filename;
get_global_ptr()->_fake_texture_image = filename;
}
////////////////////////////////////////////////////////////////////
@ -226,17 +226,5 @@ has_fake_texture_image() {
////////////////////////////////////////////////////////////////////
INLINE const string &TexturePool::
get_fake_texture_image() {
return get_ptr()->_fake_texture_image;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::Constructor
// Access: Private
// Description: The constructor is not intended to be called
// directly; there's only supposed to be one TexturePool
// in the universe and it constructs itself.
////////////////////////////////////////////////////////////////////
INLINE TexturePool::
TexturePool() {
_fake_texture_image = fake_texture_image;
return get_global_ptr()->_fake_texture_image;
}

View File

@ -20,6 +20,7 @@
#include "config_gobj.h"
#include "config_util.h"
#include "config_express.h"
#include "string_utils.h"
#include "virtualFileSystem.h"
@ -35,7 +36,79 @@ TexturePool *TexturePool::_global_ptr = (TexturePool *)NULL;
////////////////////////////////////////////////////////////////////
void TexturePool::
write(ostream &out) {
get_ptr()->ns_list_contents(out);
get_global_ptr()->ns_list_contents(out);
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::register_texture_type
// Access: Public
// Description: Records a factory function that makes a Texture
// object of the appropriate type for one or more
// particular filename extensions. The string
// extensions may be a string that contains
// space-separated list of extensions, case-insensitive.
////////////////////////////////////////////////////////////////////
void TexturePool::
register_texture_type(MakeTextureFunc *func, const string &extensions) {
vector_string words;
extract_words(downcase(extensions), words);
vector_string::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
_type_registry[*wi] = func;
}
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::make_texture
// Access: Public
// Description: Creates a new Texture object of the appropriate type
// for the indicated filename extension, according to
// the types that have been registered via
// register_texture_type().
////////////////////////////////////////////////////////////////////
PT(Texture) TexturePool::
make_texture(const string &extension) {
string c = downcase(extension);
TypeRegistry::const_iterator ti;
ti = _type_registry.find(extension);
if (ti != _type_registry.end()) {
return (*ti).second();
}
return new Texture;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::get_global_ptr
// Access: Public, Static
// Description: Initializes and/or returns the global pointer to the
// one TexturePool object in the system.
////////////////////////////////////////////////////////////////////
TexturePool *TexturePool::
get_global_ptr() {
if (_global_ptr == (TexturePool *)NULL) {
_global_ptr = new TexturePool;
}
return _global_ptr;
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::Constructor
// Access: Private
// Description: The constructor is not intended to be called
// directly; there's only supposed to be one TexturePool
// in the universe and it constructs itself.
////////////////////////////////////////////////////////////////////
TexturePool::
TexturePool() {
ConfigVariableString fake_texture_image
("fake-texture-image", "",
PRC_DESC("Set this to enable a speedy-load mode in which you don't care "
"what the world looks like, you just want it to load in minimal "
"time. This causes all texture loads via the TexturePool to use "
"the same texture file, which will presumably only be loaded "
"once."));
_fake_texture_image = fake_texture_image;
}
////////////////////////////////////////////////////////////////////
@ -91,7 +164,7 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) {
gobj_cat.info()
<< "Loading texture " << filename << "\n";
PT(Texture) tex = new Texture;
PT(Texture) tex = make_texture(filename.get_extension());
if (!tex->read(filename, 0, primary_file_num_channels)) {
// This texture was not found or could not be read.
report_texture_unreadable(filename);
@ -139,7 +212,7 @@ ns_load_texture(const Filename &orig_filename,
gobj_cat.info()
<< "Loading texture " << filename << " and alpha component "
<< alpha_filename << endl;
PT(Texture) tex = new Texture;
PT(Texture) tex = make_texture(filename.get_extension());
if (!tex->read(filename, alpha_filename, 0, primary_file_num_channels,
alpha_file_channel)) {
// This texture was not found or could not be read.
@ -186,7 +259,7 @@ ns_load_3d_texture(const HashFilename &filename_template) {
gobj_cat.info()
<< "Loading 3-d texture " << hash_filename << "\n";
PT(Texture) tex = new Texture;
PT(Texture) tex = make_texture(hash_filename.get_extension());
tex->setup_3d_texture();
if (!tex->read_pages(hash_filename)) {
// This texture was not found or could not be read.
@ -231,7 +304,7 @@ ns_load_cube_map(const HashFilename &filename_template) {
gobj_cat.info()
<< "Loading cube map texture " << hash_filename << "\n";
PT(Texture) tex = new Texture;
PT(Texture) tex = make_texture(hash_filename.get_extension());
tex->setup_cube_map();
if (!tex->read_pages(hash_filename)) {
// This texture was not found or could not be read.
@ -392,17 +465,3 @@ report_texture_unreadable(const Filename &filename) const {
<< "Texture \"" << filename << "\" exists but cannot be read.\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: TexturePool::get_ptr
// Access: Private, Static
// Description: Initializes and/or returns the global pointer to the
// one TexturePool object in the system.
////////////////////////////////////////////////////////////////////
TexturePool *TexturePool::
get_ptr() {
if (_global_ptr == (TexturePool *)NULL) {
_global_ptr = new TexturePool;
}
return _global_ptr;
}

View File

@ -68,8 +68,16 @@ PUBLISHED:
static void write(ostream &out);
public:
typedef PT(Texture) MakeTextureFunc();
void register_texture_type(MakeTextureFunc *func, const string &extensions);
PT(Texture) make_texture(const string &extension);
static TexturePool *get_global_ptr();
private:
INLINE TexturePool();
TexturePool();
bool ns_has_texture(const Filename &orig_filename);
Texture *ns_load_texture(const Filename &orig_filename, int primary_file_num_channels);
@ -89,14 +97,15 @@ private:
void report_texture_unreadable(const Filename &filename) const;
static TexturePool *get_ptr();
static TexturePool *_global_ptr;
typedef phash_map<string, PT(Texture), string_hash> Textures;
Textures _textures;
string _fake_texture_image;
PT(Texture) _normalization_cube_map;
typedef pmap<string, MakeTextureFunc *> TypeRegistry;
TypeRegistry _type_registry;
};
#include "texturePool.I"

View File

@ -0,0 +1,149 @@
// Filename: videoTexture.I
// Created by: drose (21Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::set_power_2
// Access: Published
// Description: Sets the flag that indicates whether a newly-loaded
// VideoTexture will be constrained to dimensions that are
// a power of 2 or not. If true, then a newly-loaded
// video stream will be set within the smallest power of
// 2 texture that will fit it; if false, a newly-loaded
// video stream will be set within a texture that
// exactly fits it, even if that means creating a
// texture whose dimensions are not a power of 2.
//
// This must be set before the first call to read().
// The default value is false if the Config.prc variable
// textures-power-2 is "none", true otherwise.
////////////////////////////////////////////////////////////////////
INLINE void VideoTexture::
set_power_2(bool power_2) {
_power_2 = power_2;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::get_power_2
// Access: Published
// Description: Returns the flag that indicates whether a
// newly-loaded VideoTexture will be constrained to
// dimensions that are a power of 2 or not. See
// set_power_2().
////////////////////////////////////////////////////////////////////
INLINE bool VideoTexture::
get_power_2() const {
return _power_2;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::get_video_width
// Access: Published
// Description: Returns the width in texels of the source video
// stream. This is not necessarily the width of the
// actual texture, since the texture may have been
// expanded to raise it to a power of 2.
////////////////////////////////////////////////////////////////////
INLINE int VideoTexture::
get_video_width() const {
return _video_width;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::get_video_height
// Access: Published
// Description: Returns the height in texels of the source video
// stream. This is not necessarily the height of the
// actual texture, since the texture may have been
// expanded to raise it to a power of 2.
////////////////////////////////////////////////////////////////////
INLINE int VideoTexture::
get_video_height() const {
return _video_height;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::get_tex_scale
// Access: Published
// Description: Returns a scale pair that is suitable for applying to
// geometry via NodePath::set_tex_scale(), which will
// convert texture coordinates on the geometry from the
// range 0..1 into the appropriate range to render the
// video part of the texture.
//
// This is necessary in the event the video source is
// not a power of two and set_power_2() is true. In
// this case, the video image will be mapped to the
// lower-left corner of the texture, and the rest of the
// texture space will be unused; so we will need to
// remap any texture coordinates to fill the space
// correctly.
////////////////////////////////////////////////////////////////////
INLINE LVecBase2f VideoTexture::
get_tex_scale() const {
if (_video_width == 0 || _video_height == 0 ||
_x_size == 0 || _y_size == 0) {
LVecBase2f(1.0f, 1.0f);
}
return LVecBase2f((float)_video_width / _x_size,
(float)_video_height / _y_size);
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::set_video_size
// Access: Protected
// Description: Should be called by a derived class to set the size
// of the video when it is loaded.
////////////////////////////////////////////////////////////////////
INLINE void VideoTexture::
set_video_size(int video_width, int video_height) {
_video_width = video_width;
_video_height = video_height;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::consider_update
// Access: Protected
// Description: Calls update_frame() if the current frame has
// changed.
////////////////////////////////////////////////////////////////////
INLINE void VideoTexture::
consider_update() {
int this_frame = ClockObject::get_global_clock()->get_frame_count();
if (this_frame != _last_frame_update) {
int frame = get_frame();
if (_current_frame != frame) {
update_frame(frame);
_current_frame = frame;
}
_last_frame_update = this_frame;
}
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::clear_current_frame
// Access: Protected
// Description: Resets the record of the current frame so that it
// will be forced to reload the next time it is
// requested.
////////////////////////////////////////////////////////////////////
INLINE void VideoTexture::
clear_current_frame() {
_last_frame_update = 0;
_current_frame = -1;
}

View File

@ -0,0 +1,152 @@
// Filename: videoTexture.cxx
// Created by: drose (21Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "videoTexture.h"
#include "clockObject.h"
#include "config_gobj.h"
TypeHandle VideoTexture::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
VideoTexture::
VideoTexture(const string &name) :
Texture(name)
{
_power_2 = (textures_power_2 != ATS_none);
_video_width = 0;
_video_height = 0;
_last_frame_update = 0;
_current_frame = -1;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
VideoTexture::
VideoTexture(const VideoTexture &copy) :
Texture(copy),
AnimInterface(copy),
_power_2(copy._power_2),
_video_width(copy._video_width),
_video_height(copy._video_height),
_last_frame_update(copy._last_frame_update),
_current_frame(copy._current_frame)
{
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::has_ram_image
// Access: Published, Virtual
// Description: Returns true if the Texture has its image contents
// available in main RAM, false if it exists only in
// texture memory or in the prepared GSG context.
////////////////////////////////////////////////////////////////////
bool VideoTexture::
has_ram_image() const {
int this_frame = ClockObject::get_global_clock()->get_frame_count();
if (this_frame != _last_frame_update) {
return false;
}
return !_image.empty();
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::get_keep_ram_image
// Access: Published, Virtual
// Description: Returns the flag that indicates whether this Texture
// is eligible to have its main RAM copy of the texture
// memory dumped when the texture is prepared for
// rendering. See set_keep_ram_image().
////////////////////////////////////////////////////////////////////
bool VideoTexture::
get_keep_ram_image() const {
// An VideoTexture should never dump its RAM image.
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::has_cull_callback
// Access: Public, Virtual
// Description: Should be overridden by derived classes to return
// true if cull_callback() has been defined. Otherwise,
// returns false to indicate cull_callback() does not
// need to be called for this node during the cull
// traversal.
////////////////////////////////////////////////////////////////////
bool VideoTexture::
has_cull_callback() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::cull_callback
// Access: Public, Virtual
// Description: If has_cull_callback() returns true, this function
// will be called during the cull traversal to perform
// any additional operations that should be performed at
// cull time.
//
// This is called each time the Texture is discovered
// applied to a Geom in the traversal. It should return
// true if the Geom is visible, false if it should be
// omitted.
////////////////////////////////////////////////////////////////////
bool VideoTexture::
cull_callback(CullTraverser *, const CullTraverserData &) const {
// Strictly speaking, the cull_callback() method isn't necessary for
// VideoTexture, since the get_ram_image() function is already
// overloaded to update itself if necessary. However, we define it
// anyway, to move the update calculation into the cull traversal
// rather than the draw traversal.
((VideoTexture *)this)->reconsider_dirty();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::reconsider_dirty
// Access: Protected, Virtual
// Description: Called by TextureContext to give the Texture a chance
// to mark itself dirty before rendering, if necessary.
////////////////////////////////////////////////////////////////////
void VideoTexture::
reconsider_dirty() {
consider_update();
}
////////////////////////////////////////////////////////////////////
// Function: VideoTexture::reload_ram_image
// Access: Protected, Virtual
// Description: Called when the Texture image is required but the ram
// image is not available, this will reload it from disk
// or otherwise do whatever is required to make it
// available, if possible.
////////////////////////////////////////////////////////////////////
void VideoTexture::
reload_ram_image() {
consider_update();
}

View File

@ -0,0 +1,93 @@
// Filename: videoTexture.h
// Created by: drose (21Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VIDEOTEXTURE_H
#define VIDEOTEXTURE_H
#include "pandabase.h"
#include "texture.h"
#include "animInterface.h"
////////////////////////////////////////////////////////////////////
// Class : VideoTexture
// Description : The base class for a family of animated Textures that
// take their input from a video source, such as a movie
// file. These Textures may be stopped, started,
// etc. using the AnimInterface controls, similar to an
// animated character.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VideoTexture : public Texture, public AnimInterface {
protected:
VideoTexture(const string &name);
VideoTexture(const VideoTexture &copy);
PUBLISHED:
INLINE void set_power_2(bool power_2);
INLINE bool get_power_2() const;
virtual bool has_ram_image() const;
virtual bool get_keep_ram_image() const;
INLINE int get_video_width() const;
INLINE int get_video_height() const;
INLINE LVecBase2f get_tex_scale() const;
public:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
protected:
INLINE void set_video_size(int video_width, int video_height);
virtual void reconsider_dirty();
virtual void reload_ram_image();
INLINE void consider_update();
INLINE void clear_current_frame();
virtual void update_frame(int frame)=0;
private:
bool _power_2;
int _video_width;
int _video_height;
int _last_frame_update;
int _current_frame;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
Texture::init_type();
AnimInterface::init_type();
register_type(_type_handle, "VideoTexture",
Texture::get_class_type(),
AnimInterface::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "videoTexture.I"
#endif

View File

@ -1,7 +1,7 @@
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#define USE_PACKAGES cv
#define USE_PACKAGES opencv
#begin lib_target
#define TARGET grutil
@ -16,13 +16,13 @@
frameRateMeter.I frameRateMeter.h \
lineSegs.I lineSegs.h \
multitexReducer.I multitexReducer.h multitexReducer.cxx \
aviTexture.h aviTexture.I
openCVTexture.h openCVTexture.I
#define INCLUDED_SOURCES \
cardMaker.cxx \
config_grutil.cxx \
frameRateMeter.cxx \
aviTexture.cxx \
openCVTexture.cxx \
lineSegs.cxx
@ -31,7 +31,7 @@
frameRateMeter.I frameRateMeter.h \
lineSegs.I lineSegs.h \
multitexReducer.I multitexReducer.h \
aviTexture.I aviTexture.h
openCVTexture.I openCVTexture.h
#define IGATESCAN all

View File

@ -1,134 +0,0 @@
// Filename: aviTexture.I
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: AviTexture::obtain_ram
// Access: Private
// Description: Grabs a fresh ram buffer to mess with
//
////////////////////////////////////////////////////////////////////
INLINE bool AviTexture::
obtain_ram() {
_buf = modify_ram_image();
if (_buf) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::get_time
// Access: Published
// Description: returns the ratio between 0 and 1 that the movie is
// positioned at. Disabled for camera input
//
////////////////////////////////////////////////////////////////////
INLINE float AviTexture::
get_time() {
if (!_isCamera) {
return _time;
}
return 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::set_time
// Access: Published
// Description: sets the time on the opencv video reader. Disabled
// for camera input
//
////////////////////////////////////////////////////////////////////
INLINE void AviTexture::
set_time(float t) {
if (_isCamera) {
return;
}
if (t >= 0 && t <= 1) {
_time=t;
}
if (_capture) {
cvSetCaptureProperty(_capture,CV_CAP_PROP_POS_AVI_RATIO,t);
_current_frame = cvGetCaptureProperty(_capture,CV_CAP_PROP_POS_FRAMES);
}
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::set_fps
// Access: Published
// Description: sets the fps for the movie, and affects frame receives
// from camera. Note, since frame update is controlled
// by python, this item is sort of arbitrary
////////////////////////////////////////////////////////////////////
INLINE void AviTexture::
set_fps(float fps) {
if (fps >= 0) {
_fps = fps;
} else {
return;
}
if (_isCamera && _capture) {
cvSetCaptureProperty(_capture,CV_CAP_PROP_FPS,int(fps));
}
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::get_fps
// Access: Published
// Description: returns the fps as recieved from movie
////////////////////////////////////////////////////////////////////
INLINE float AviTexture::
get_fps() {
return _fps;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::get_total_frames
// Access: Published
// Description: returns the total amount of frames
////////////////////////////////////////////////////////////////////
INLINE int AviTexture::
get_total_frames() {
return _total_frames;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::get_current_frame
// Access: Published
// Description: returns current frame (base 0)
////////////////////////////////////////////////////////////////////
INLINE int AviTexture::
get_current_frame() {
return _current_frame;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::set_current_frame
// Access: Published
// Description: sets the current frame (base 0)
////////////////////////////////////////////////////////////////////
INLINE void AviTexture::
set_current_frame(int frame) {
if (frame>=0 && frame<_total_frames) {
_current_frame = frame;
cvSetCaptureProperty(_capture,CV_CAP_PROP_POS_FRAMES,_current_frame);
_time = cvGetCaptureProperty(_capture,CV_CAP_PROP_POS_AVI_RATIO);
}
}

View File

@ -1,163 +0,0 @@
// Filename: aviTexture.cxx
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#ifdef HAVE_CV
#include "aviTexture.h"
TypeHandle AviTexture::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: AviTexture::Constructor
// Access: Published
// Description: Sets up the texture to read frames from a camera
////////////////////////////////////////////////////////////////////
AviTexture::
AviTexture() {
_isCamera = true;
_capture = cvCaptureFromCAM(0);
_buf = NULL;
_magicNum = 0;
_time = 0.0f;
_fps = 30.0f;
_total_frames = 0;
_current_frame = 0;
if (_capture) {
cvSetCaptureProperty(_capture, CV_CAP_PROP_FPS,_fps);
_width = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
_height = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
if (_width < _height) {
gen_tex(_width);
} else {
gen_tex(_height);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::Constructor
// Access: Published
// Description: Defines the texture as a movie texture.
// TODO: Make this search the panda paths
////////////////////////////////////////////////////////////////////
AviTexture::
AviTexture(const string &filename) {
_isCamera = false;
_capture = cvCaptureFromFile(filename.c_str());
_buf = NULL;
_magicNum = 0;
_time = 0.0f;
_fps = 30.0f;
_total_frames = 0;
_current_frame = 0;
if (_capture) {
_fps = cvGetCaptureProperty(_capture, CV_CAP_PROP_FPS);
_total_frames = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_COUNT);
_width = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
_height = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
if (_width < _height) {
gen_tex(_width);
} else {
gen_tex(_height);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::Destructor
// Access: Published
// Description: Destructor. Release the camera or video stream
////////////////////////////////////////////////////////////////////
AviTexture::
~AviTexture() {
cvReleaseCapture(&_capture);
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::gen_tex
// Access: Published
// Description: Tries to find the largest texture that will fit
// inside the video stream. TODO: allow for fit around
////////////////////////////////////////////////////////////////////
void AviTexture::
gen_tex(int magicNum) {
int size = down_to_power_2(magicNum);
setup_2d_texture(size, size, Texture::T_unsigned_byte, Texture::F_rgb8);
_magicNum = size;
}
////////////////////////////////////////////////////////////////////
// Function: AviTexture::update
// Access: Published
// Description: Grabs the next frame off the camera or avi file
// Returns false if the capture fails or reached EOF
////////////////////////////////////////////////////////////////////
bool AviTexture::
update() {
int begx, endx, begy, endy;
IplImage *frame = 0;
int xs, ys;
if (_capture) {
if (_time == 1.0f) {
return false;
}
frame = cvQueryFrame( _capture );
if (frame) {
_time = cvGetCaptureProperty(_capture, CV_CAP_PROP_POS_AVI_RATIO);
_current_frame = cvGetCaptureProperty(_capture, CV_CAP_PROP_POS_FRAMES);
if (!obtain_ram()) {
return false;
}
begx = (_width - _magicNum) / 2.0;
endx = _width - begx;
begy = (_height - _magicNum) / 2.0;
endy = _height - begy;
if (_buf) {
xs = get_x_size();
ys = get_y_size();
if (get_num_components() != 3) {
return false;
}
for (int i = begy; i < endy; ++i) {
memcpy(_buf + ((i - begy) * xs * 3),
frame->imageData + i * _width * 3 + begx * 3,
xs * 3);
}
return true;
}
}
}
return false;
}
#endif // HAVE_CV

View File

@ -1,94 +0,0 @@
// Filename: aviTexture.h
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef AVITEXTURE_H
#define AVITEXTURE_H
#include "pandabase.h"
#ifdef HAVE_CV
#include "texture.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
////////////////////////////////////////////////////////////////////
// Class : AviTexture
// Description : A specialization on Texture that takes its input
// using the CV library, to produce an animated texture,
// with its source taken from an .avi file or from a
// camera input.
//
// Presently, it is necessary for the application to
// call update() periodically to advance to the next
// frame.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AviTexture : public Texture {
PUBLISHED:
AviTexture();
AviTexture(const string &filename);
~AviTexture();
INLINE void set_time(float t);
INLINE float get_time();
INLINE float get_fps();
INLINE void set_fps(float fps);
INLINE int get_total_frames();
INLINE int get_current_frame();
INLINE void set_current_frame(int frame);
bool update();
private:
void gen_tex(int magicNum);
INLINE bool obtain_ram();
int _magicNum;
PTA_uchar _buf;
CvCapture * _capture;
float _time;
bool _isCamera;
float _fps;
int _total_frames;
int _current_frame;
int _width;
int _height;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
Texture::init_type();
register_type(_type_handle, "AviTexture",
Texture::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "aviTexture.I"
#endif // HAVE_CV
#endif

View File

@ -18,7 +18,9 @@
#include "config_grutil.h"
#include "frameRateMeter.h"
#include "aviTexture.h"
#include "openCVTexture.h"
#include "pandaSystem.h"
#include "texturePool.h"
#include "dconfig.h"
@ -63,8 +65,13 @@ init_libgrutil() {
FrameRateMeter::init_type();
#ifdef HAVE_CV
AviTexture::init_type();
#endif // HAVE_CV
#ifdef HAVE_OPENCV
OpenCVTexture::init_type();
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->add_system("OpenCV");
TexturePool *ts = TexturePool::get_global_ptr();
ts->register_texture_type(OpenCVTexture::make_texture, "avi");
#endif // HAVE_OPENCV
}

View File

@ -2,5 +2,5 @@
#include "config_grutil.cxx"
#include "lineSegs.cxx"
#include "frameRateMeter.cxx"
#include "aviTexture.cxx"
#include "openCVTexture.cxx"

View File

@ -0,0 +1,70 @@
// Filename: openCVTexture.I
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::is_valid
// Access: Public
// Description: Returns true if this stream is open and ready, false
// otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool OpenCVTexture::VideoStream::
is_valid() const {
return (_capture != NULL);
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::is_from_file
// Access: Public
// Description: Returns true if this stream takes its input from a
// video file, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool OpenCVTexture::VideoStream::
is_from_file() const {
return !_filename.empty();
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoPage::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE OpenCVTexture::VideoPage::
VideoPage() {
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoPage::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE OpenCVTexture::VideoPage::
VideoPage(const OpenCVTexture::VideoPage &copy) :
_color(copy._color),
_alpha(copy._alpha)
{
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoPage::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE OpenCVTexture::VideoPage::
~VideoPage() {
}

View File

@ -0,0 +1,526 @@
// Filename: openCVTexture.cxx
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#ifdef HAVE_OPENCV
#include "openCVTexture.h"
#include "clockObject.h"
#include "config_gobj.h"
#include "config_grutil.h"
TypeHandle OpenCVTexture::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::Constructor
// Access: Published
// Description: Sets up the texture to read frames from a camera
////////////////////////////////////////////////////////////////////
OpenCVTexture::
OpenCVTexture(const string &name) :
VideoTexture(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::Copy Constructor
// Access: Protected
// Description: Use OpenCVTexture::make_copy() to make a duplicate copy of
// an existing OpenCVTexture.
////////////////////////////////////////////////////////////////////
OpenCVTexture::
OpenCVTexture(const OpenCVTexture &copy) :
VideoTexture(copy),
_pages(copy._pages)
{
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
OpenCVTexture::
~OpenCVTexture() {
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::make_copy
// Access: Published, Virtual
// Description: Returns a new copy of the same Texture. This copy,
// if applied to geometry, will be copied into texture
// as a separate texture from the original, so it will
// be duplicated in texture memory (and may be
// independently modified if desired).
//
// If the Texture is an OpenCVTexture, the resulting
// duplicate may be animated independently of the
// original.
////////////////////////////////////////////////////////////////////
PT(Texture) OpenCVTexture::
make_copy() {
return new OpenCVTexture(*this);
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::from_camera
// Access: Published, Virtual
// Description: Sets up the OpenCVTexture (or the indicated page, if z
// is specified) to accept its input from the camera
// with the given index number, or the default camera if
// the index number is -1 or unspecified.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::
from_camera(int camera_index, int z) {
if (!reconsider_z_size(z)) {
return false;
}
nassertr(z >= 0 && z < get_z_size(), false);
VideoPage &page = modify_page(z);
page._alpha.clear();
if (!page._color.from_camera(camera_index)) {
return false;
}
int width = cvGetCaptureProperty(page._color._capture, CV_CAP_PROP_FRAME_WIDTH);
int height = cvGetCaptureProperty(page._color._capture, CV_CAP_PROP_FRAME_HEIGHT);
if (!reconsider_video_properties(page._color, 3, z)) {
page._color.clear();
return false;
}
set_loaded_from_disk();
clear_current_frame();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::read
// Access: Published, Virtual
// Description: Takes the video image from the indicated filename.
// If the filename is not a video file, attempts to read
// it as a still image instead.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::
read(const Filename &fullpath, int z, int) {
if (!reconsider_z_size(z)) {
return false;
}
nassertr(z >= 0 && z < get_z_size(), false);
VideoPage &page = modify_page(z);
page._alpha.clear();
if (!page._color.read(fullpath)) {
grutil_cat.error()
<< "OpenCV couldn't read " << fullpath << " as video.\n";
return false;
}
if (!has_name()) {
set_name(fullpath.get_basename_wo_extension());
}
if (!has_filename()) {
set_filename(fullpath);
clear_alpha_filename();
}
set_fullpath(fullpath);
clear_alpha_fullpath();
_primary_file_num_channels = 3;
_alpha_file_channel = 0;
if (!reconsider_video_properties(page._color, 3, z)) {
page._color.clear();
return false;
}
set_loaded_from_disk();
clear_current_frame();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::read
// Access: Published, Virtual
// Description: Combines a color and alpha video image from the two
// indicated filenames. Both must be the same kind of
// video with similar properties.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::
read(const Filename &fullpath, const Filename &alpha_fullpath,
int z, int, int alpha_file_channel) {
if (!reconsider_z_size(z)) {
return false;
}
nassertr(z >= 0 && z < get_z_size(), false);
VideoPage &page = modify_page(z);
if (!page._color.read(fullpath)) {
grutil_cat.error()
<< "OpenCV couldn't read " << fullpath << " as video.\n";
return false;
}
if (!page._alpha.read(alpha_fullpath)) {
grutil_cat.error()
<< "OpenCV couldn't read " << alpha_fullpath << " as video.\n";
page._color.clear();
return false;
}
if (!has_name()) {
set_name(fullpath.get_basename_wo_extension());
}
if (!has_filename()) {
set_filename(fullpath);
set_alpha_filename(alpha_fullpath);
}
set_fullpath(fullpath);
set_alpha_fullpath(alpha_fullpath);
_primary_file_num_channels = 3;
_alpha_file_channel = alpha_file_channel;
if (!reconsider_video_properties(page._color, 4, z)) {
page._color.clear();
page._alpha.clear();
return false;
}
if (!reconsider_video_properties(page._alpha, 4, z)) {
page._color.clear();
page._alpha.clear();
return false;
}
set_loaded_from_disk();
clear_current_frame();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::load
// Access: Published, Virtual
// Description: Resets the texture (or the particular level of the
// texture) to the indicated static image.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::
load(const PNMImage &pnmimage, int z) {
if (z <= (int)_pages.size()) {
VideoPage &page = modify_page(z);
page._color.clear();
page._alpha.clear();
}
return Texture::load(pnmimage, z);
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::modify_page
// Access: Private
// Description: Returns a reference to the zth VideoPage (level) of
// the texture. In the case of a 2-d texture, there is
// only one page, level 0; but cube maps and 3-d
// textures have more.
////////////////////////////////////////////////////////////////////
OpenCVTexture::VideoPage &OpenCVTexture::
modify_page(int z) {
nassertr(z < _z_size, _pages[0]);
while (z >= (int)_pages.size()) {
_pages.push_back(VideoPage());
}
return _pages[z];
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::reconsider_video_properties
// Access: Private
// Description: Resets the internal Texture properties when a new
// video file is loaded. Returns true if the new image
// is valid, false otherwise.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::
reconsider_video_properties(const OpenCVTexture::VideoStream &stream,
int num_components, int z) {
double frame_rate = 0.0f;
int num_frames = 0;
if (stream.is_from_file()) {
frame_rate = cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FPS);
num_frames = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_COUNT);
}
int width = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_WIDTH);
int height = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_HEIGHT);
int x_size = width;
int y_size = height;
if (get_power_2()) {
x_size = up_to_power_2(width);
y_size = up_to_power_2(height);
}
if (!reconsider_image_properties(x_size, y_size, num_components,
T_unsigned_byte, z)) {
return false;
}
if (_loaded_from_disk &&
(get_video_width() != width || get_video_height() != height ||
get_num_frames() != num_frames || get_frame_rate() != frame_rate)) {
grutil_cat.error()
<< "Video properties have changed for texture " << get_name()
<< " level " << z << ".\n";
return false;
}
set_frame_rate(frame_rate);
set_num_frames(num_frames);
set_video_size(width, height);
// By default, the newly-loaded video stream will immediately start
// looping.
loop(true);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::make_texture
// Access: Public, Static
// Description: A factory function to make a new OpenCVTexture, used
// to pass to the TexturePool.
////////////////////////////////////////////////////////////////////
PT(Texture) OpenCVTexture::
make_texture() {
return new OpenCVTexture;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::update_frame
// Access: Protected, Virtual
// Description: Called once per frame, as needed, to load the new
// image contents.
////////////////////////////////////////////////////////////////////
void OpenCVTexture::
update_frame(int frame) {
int max_z = max(_z_size, (int)_pages.size());
for (int z = 0; z < max_z; ++z) {
VideoPage &page = _pages[z];
if (page._color.is_valid() || page._alpha.is_valid()) {
modify_ram_image();
}
if (page._color.is_valid()) {
nassertv(get_num_components() >= 3 && get_component_width() == 1);
const unsigned char *source = page._color.get_frame_data(frame);
if (source != NULL) {
nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size);
unsigned char *dest = _image.p() + get_expected_ram_page_size() * z;
int dest_row_width = (_x_size * _num_components * _component_width);
int source_row_width = get_video_width() * 3;
if (get_num_components() == 3) {
// The easy case--copy the whole thing in, row by row.
for (int y = 0; y < get_video_height(); ++y) {
memcpy(dest, source, source_row_width);
dest += dest_row_width;
source += source_row_width;
}
} else {
// The harder case--interleave the color in with the alpha,
// pixel by pixel.
nassertv(get_num_components() == 4);
for (int y = 0; y < get_video_height(); ++y) {
int dx = 0;
int sx = 0;
for (int x = 0; x < get_video_width(); ++x) {
dest[dx] = source[sx];
dest[dx + 1] = source[sx + 1];
dest[dx + 2] = source[sx + 2];
dx += 4;
sx += 3;
}
dest += dest_row_width;
source += source_row_width;
}
}
}
}
if (page._alpha.is_valid()) {
nassertv(get_num_components() == 4 && get_component_width() == 1);
const unsigned char *source = page._alpha.get_frame_data(frame);
if (source != NULL) {
nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size);
unsigned char *dest = _image.p() + get_expected_ram_page_size() * z;
int dest_row_width = (_x_size * _num_components * _component_width);
int source_row_width = get_video_width() * 3;
// Interleave the alpha in with the color, pixel by pixel.
// Even though the alpha will probably be a grayscale video,
// the OpenCV library presents it as RGB.
for (int y = 0; y < get_video_height(); ++y) {
int dx = 3;
int sx = _alpha_file_channel;
for (int x = 0; x < get_video_width(); ++x) {
dest[dx] = source[sx];
dx += 4;
sx += 3;
}
dest += dest_row_width;
source += source_row_width;
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
OpenCVTexture::VideoStream::
VideoStream() :
_capture(NULL),
_camera_index(-1),
_next_frame(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
OpenCVTexture::VideoStream::
VideoStream(const OpenCVTexture::VideoStream &copy) :
_capture(NULL),
_camera_index(-1)
{
// Rather than copying the _capture pointer, we must open a new
// stream that references the same file.
if (copy.is_valid()) {
if (copy.is_from_file()) {
read(copy._filename);
} else {
from_camera(copy._camera_index);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
OpenCVTexture::VideoStream::
~VideoStream() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::get_frame_data
// Access: Public
// Description: Returns the pointer to the beginning of the
// decompressed buffer for the indicated frame number.
// It is most efficient to call this in increasing order
// of frame number.
////////////////////////////////////////////////////////////////////
const unsigned char *OpenCVTexture::VideoStream::
get_frame_data(int frame) {
nassertr(is_valid(), NULL);
if (is_from_file() && _next_frame != frame) {
cvSetCaptureProperty(_capture, CV_CAP_PROP_POS_FRAMES, frame);
}
_next_frame = frame + 1;
IplImage *image = cvQueryFrame(_capture);
if (image == NULL) {
return NULL;
}
return (const unsigned char *)image->imageData;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::read
// Access: Public
// Description: Sets up the stream to read the indicated file.
// Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::VideoStream::
read(const Filename &filename) {
clear();
string os_specific = filename.to_os_specific();
_capture = cvCaptureFromFile(os_specific.c_str());
if (_capture == NULL) {
return false;
}
_filename = filename;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::from_camera
// Access: Public
// Description: Sets up the stream to display the indicated camera.
// Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool OpenCVTexture::VideoStream::
from_camera(int camera_index) {
clear();
_capture = cvCaptureFromCAM(camera_index);
if (_capture == NULL) {
return false;
}
_camera_index = camera_index;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: OpenCVTexture::VideoStream::clear
// Access: Public
// Description: Stops the video playback and frees the associated
// resources.
////////////////////////////////////////////////////////////////////
void OpenCVTexture::VideoStream::
clear() {
if (_capture != NULL) {
cvReleaseCapture(&_capture);
_capture = NULL;
}
_filename = Filename();
_camera_index = -1;
_next_frame = 0;
}
#endif // HAVE_OPENCV

View File

@ -0,0 +1,125 @@
// Filename: openCVTexture.h
// Created by: zacpavlov (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef OPENCVTEXTURE_H
#define OPENCVTEXTURE_H
#include "pandabase.h"
#ifdef HAVE_OPENCV
#include "videoTexture.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
////////////////////////////////////////////////////////////////////
// Class : OpenCVTexture
// Description : A specialization on VideoTexture that takes its input
// using the CV library, to produce an animated texture,
// with its source taken from an .avi file or from a
// camera input.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA OpenCVTexture : public VideoTexture {
PUBLISHED:
OpenCVTexture(const string &name = string());
protected:
OpenCVTexture(const OpenCVTexture &copy);
PUBLISHED:
virtual ~OpenCVTexture();
virtual PT(Texture) make_copy();
bool from_camera(int camera_index = -1, int z = 0);
virtual bool read(const Filename &fullpath, int z = 0,
int primary_file_num_channels = 0);
virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath,
int z = 0,
int primary_file_num_channels = 0, int alpha_file_channel = 0);
virtual bool load(const PNMImage &pnmimage, int z = 0);
public:
static PT(Texture) make_texture();
protected:
virtual void update_frame(int frame);
private:
class VideoPage;
class VideoStream;
VideoPage &modify_page(int z);
bool reconsider_video_properties(const VideoStream &stream,
int num_components, int z);
void do_update();
class VideoStream {
public:
VideoStream();
VideoStream(const VideoStream &copy);
~VideoStream();
bool read(const Filename &filename);
bool from_camera(int camera_index);
void clear();
INLINE bool is_valid() const;
INLINE bool is_from_file() const;
const unsigned char *get_frame_data(int frame);
CvCapture *_capture;
Filename _filename;
int _camera_index;
int _next_frame;
};
class VideoPage {
public:
INLINE VideoPage();
INLINE VideoPage(const VideoPage &copy);
INLINE ~VideoPage();
VideoStream _color, _alpha;
};
typedef pvector<VideoPage> Pages;
Pages _pages;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
VideoTexture::init_type();
register_type(_type_handle, "OpenCVTexture",
VideoTexture::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "openCVTexture.I"
#endif // HAVE_OPENCV
#endif

View File

@ -214,7 +214,12 @@ traverse_below(CullTraverserData &data) {
_geoms_pcollector.add_level(num_geoms);
for (int i = 0; i < num_geoms; i++) {
CullableObject *object = new CullableObject(data, geom_node, i);
_cull_handler->record_object(object, this);
if (object->_state->has_cull_callback() &&
!object->_state->cull_callback(this, data)) {
delete object;
} else {
_cull_handler->record_object(object, this);
}
}
}
@ -533,7 +538,14 @@ start_decal(const CullTraverserData &data) {
int num_geoms = geom_node->get_num_geoms();
_geoms_pcollector.add_level(num_geoms);
for (int i = num_geoms - 1; i >= 0; i--) {
object = new CullableObject(data, geom_node, i, object);
CullableObject *next_object =
new CullableObject(data, geom_node, i, object);
if (next_object->_state->has_cull_callback() &&
!next_object->_state->cull_callback(this, data)) {
delete next_object;
} else {
object = next_object;
}
}
if (object != separator) {
@ -591,7 +603,14 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) {
int num_geoms = geom_node->get_num_geoms();
_geoms_pcollector.add_level(num_geoms);
for (int i = num_geoms - 1; i >= 0; i--) {
decals = new CullableObject(data, geom_node, i, decals);
CullableObject *next_decals =
new CullableObject(data, geom_node, i, decals);
if (next_decals->_state->has_cull_callback() &&
!next_decals->_state->cull_callback(this, data)) {
delete next_decals;
} else {
decals = next_decals;
}
}
}
}

View File

@ -125,6 +125,38 @@ lower_attrib_can_override() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::has_cull_callback
// Access: Public, Virtual
// Description: Should be overridden by derived classes to return
// true if cull_callback() has been defined. Otherwise,
// returns false to indicate cull_callback() does not
// need to be called for this node during the cull
// traversal.
////////////////////////////////////////////////////////////////////
bool RenderAttrib::
has_cull_callback() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::cull_callback
// Access: Public, Virtual
// Description: If has_cull_callback() returns true, this function
// will be called during the cull traversal to perform
// any additional operations that should be performed at
// cull time.
//
// This is called each time the RenderAttrib is
// discovered applied to a Geom in the traversal. It
// should return true if the Geom is visible, false if
// it should be omitted.
////////////////////////////////////////////////////////////////////
bool RenderAttrib::
cull_callback(CullTraverser *, const CullTraverserData &) const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::output
// Access: Published, Virtual

View File

@ -27,6 +27,8 @@
class AttribSlots;
class GraphicsStateGuardianBase;
class CullTraverser;
class CullTraverserData;
////////////////////////////////////////////////////////////////////
// Class : RenderAttrib
@ -73,6 +75,9 @@ public:
INLINE bool always_reissue() const;
virtual void store_into_slot(AttribSlots *slots) const=0;
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
PUBLISHED:
INLINE int compare_to(const RenderAttrib &other) const;
virtual void output(ostream &out) const;

View File

@ -61,6 +61,23 @@ get_override(int n) const {
return _attributes[n]._override;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::has_cull_callback
// Access: Published
// Description: Returns true if any of the RenderAttribs in this
// state request a cull_callback(), false if none of
// them do.
////////////////////////////////////////////////////////////////////
INLINE bool RenderState::
has_cull_callback() const {
if ((_flags & F_checked_cull_callback) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal shader cache.
((RenderState *)this)->determine_cull_callback();
}
return (_flags & F_has_cull_callback) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::cache_ref
// Access: Published

View File

@ -136,6 +136,26 @@ operator < (const RenderState &other) const {
CompareTo<Attribute>());
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::cull_callback
// Access: Published
// Description: Calls cull_callback() on each attrib. If any attrib
// returns false, interrupts the list and returns false
// immediately; otherwise, completes the list and
// returns true.
////////////////////////////////////////////////////////////////////
bool RenderState::
cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
Attributes::const_iterator ai;
for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
const Attribute &attrib = *ai;
if (!attrib._attrib->cull_callback(trav, data)) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::find_attrib
@ -1570,6 +1590,25 @@ determine_shader() {
_flags |= F_checked_shader;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_cull_callback
// Access: Private
// Description: This is the private implementation of has_cull_callback().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_cull_callback() {
Attributes::const_iterator ai;
for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
const Attribute &attrib = *ai;
if (attrib._attrib->has_cull_callback()) {
_flags |= F_has_cull_callback;
break;
}
}
_flags |= F_checked_cull_callback;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::update_pstats
// Access: Private

View File

@ -75,6 +75,9 @@ PUBLISHED:
INLINE const RenderAttrib *get_attrib(int n) const;
INLINE int get_override(int n) const;
INLINE bool has_cull_callback() const;
bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
int find_attrib(TypeHandle type) const;
static CPT(RenderState) make_empty();
@ -181,6 +184,7 @@ private:
void determine_render_mode();
void determine_clip_plane();
void determine_shader();
void determine_cull_callback();
INLINE void set_destructing();
INLINE bool is_destructing() const;
@ -282,19 +286,21 @@ private:
const ShaderAttrib *_shader;
enum Flags {
F_checked_bin_index = 0x0001,
F_checked_fog = 0x0002,
F_checked_bin = 0x0004,
F_checked_transparency = 0x0008,
F_checked_color = 0x0010,
F_checked_color_scale = 0x0020,
F_checked_texture = 0x0040,
F_checked_tex_gen = 0x0080,
F_checked_tex_matrix = 0x0100,
F_checked_render_mode = 0x0200,
F_checked_clip_plane = 0x0400,
F_checked_shader = 0x0800,
F_is_destructing = 0x8000,
F_checked_bin_index = 0x0001,
F_checked_fog = 0x0002,
F_checked_bin = 0x0004,
F_checked_transparency = 0x0008,
F_checked_color = 0x0010,
F_checked_color_scale = 0x0020,
F_checked_texture = 0x0040,
F_checked_tex_gen = 0x0080,
F_checked_tex_matrix = 0x0100,
F_checked_render_mode = 0x0200,
F_checked_clip_plane = 0x0400,
F_checked_shader = 0x0800,
F_checked_cull_callback = 0x1000,
F_has_cull_callback = 0x2000,
F_is_destructing = 0x8000,
};
unsigned short _flags;

View File

@ -390,6 +390,54 @@ output(ostream &out) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::has_cull_callback
// Access: Public, Virtual
// Description: Should be overridden by derived classes to return
// true if cull_callback() has been defined. Otherwise,
// returns false to indicate cull_callback() does not
// need to be called for this node during the cull
// traversal.
////////////////////////////////////////////////////////////////////
bool TextureAttrib::
has_cull_callback() const {
OnTextures::const_iterator nti;
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
Texture *texture = (*nti).second;
if (texture->has_cull_callback()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::cull_callback
// Access: Public, Virtual
// Description: If has_cull_callback() returns true, this function
// will be called during the cull traversal to perform
// any additional operations that should be performed at
// cull time.
//
// This is called each time the RenderAttrib is
// discovered applied to a Geom in the traversal. It
// should return true if the Geom is visible, false if
// it should be omitted.
////////////////////////////////////////////////////////////////////
bool TextureAttrib::
cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
OnTextures::const_iterator nti;
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
Texture *texture = (*nti).second;
if (!texture->cull_callback(trav, data)) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::compare_to_impl
// Access: Protected, Virtual

View File

@ -84,6 +84,9 @@ public:
virtual void output(ostream &out) const;
virtual void store_into_slot(AttribSlots *slots) const;
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;

View File

@ -8,6 +8,7 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
animInterface.h animInterface.I \
bam.h bamEndian.h \
bamReader.I bamReader.N bamReader.h bamReaderParam.I \
bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \
@ -60,6 +61,7 @@
writableParam.I writableParam.h
#define INCLUDED_SOURCES \
animInterface.cxx \
bamEndian.cxx \
bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \
buttonHandle.cxx buttonRegistry.cxx \
@ -96,6 +98,7 @@
writableConfigurable.cxx writableParam.cxx
#define INSTALL_HEADERS \
animInterface.h animInterface.I \
bam.h bamEndian.h \
bamReader.I bamReader.h bamReaderParam.I bamReaderParam.h \
bamWriter.I bamWriter.h bitMask.I bitMask.h \

View File

@ -0,0 +1,178 @@
// Filename: animInterface.I
// Created by: drose (20Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::play
// Access: Published
// Description: Runs the entire animation from beginning to end and
// stops.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
play() {
play(0, get_num_frames() - 1);
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::loop
// Access: Published
// Description: Starts the entire animation looping. If restart is
// true, the animation is restarted from the beginning;
// otherwise, it continues from the current frame.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
loop(bool restart) {
loop(restart, 0, get_num_frames() - 1);
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::pingpong
// Access: Published
// Description: Starts the entire animation bouncing back and forth
// between its first frame and last frame. If restart
// is true, the animation is restarted from the
// beginning; otherwise, it continues from the current
// frame.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
pingpong(bool restart) {
pingpong(restart, 0, get_num_frames() - 1);
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::stop
// Access: Published
// Description: Stops a currently playing or looping animation right
// where it is. The animation remains posed at the
// current frame.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
stop() {
pose(get_frame());
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::set_play_rate
// Access: Published
// Description: Changes the rate at which the animation plays. 1.0
// is the normal speed, 2.0 is twice normal speed, and
// 0.5 is half normal speed. 0.0 is legal to pause the
// animation, and a negative value will play the
// animation backwards.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
set_play_rate(double play_rate) {
internal_set_rate(_frame_rate, play_rate);
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_play_rate
// Access: Published
// Description: Returns the rate at which the animation plays. See
// set_play_rate().
////////////////////////////////////////////////////////////////////
INLINE double AnimInterface::
get_play_rate() const {
return _play_rate;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_frame_rate
// Access: Published
// Description: Returns the native frame rate of the animation. This
// is the number of frames per second that will elapse
// when the play_rate is set to 1.0. It is a fixed
// property of the animation and may not be adjusted by
// the user.
////////////////////////////////////////////////////////////////////
INLINE double AnimInterface::
get_frame_rate() const {
return _frame_rate;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_num_frames
// Access: Published
// Description: Returns the number of frames in the animation. This
// is a fixed property of the animation and may not be
// adjusted by the user.
////////////////////////////////////////////////////////////////////
INLINE int AnimInterface::
get_num_frames() const {
return _num_frames;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_frame
// Access: Published
// Description: Returns the current integer frame number.
// This number will be in the range 0 <= f <
// get_num_frames().
////////////////////////////////////////////////////////////////////
INLINE int AnimInterface::
get_frame() const {
return cmod(get_full_frame(), get_num_frames());
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_frac
// Access: Published
// Description: Returns the fractional part of the current frame.
// Normally, this is in the range 0.0 <= f < 1.0, but in
// the one special case of an animation playing to its
// end frame and stopping, it might exactly equal 1.0.
//
// It will always be true that get_full_frame() +
// get_frac() == get_full_fframe().
////////////////////////////////////////////////////////////////////
INLINE double AnimInterface::
get_frac() const {
return get_full_fframe() - (double)get_full_frame();
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::set_frame_rate
// Access: Protected
// Description: Should be called by a derived class to specify the
// native frame rate of the animation. It is legal to
// call this after the animation has already started.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
set_frame_rate(double frame_rate) {
internal_set_rate(frame_rate, _play_rate);
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::set_num_frames
// Access: Protected
// Description: Should be called by a derived class to specify the
// number of frames of the animation. It is legal to
// call this after the animation has already started,
// but doing so may suddenly change the apparent current
// frame number.
////////////////////////////////////////////////////////////////////
INLINE void AnimInterface::
set_num_frames(int num_frames) {
_num_frames = num_frames;
}
INLINE ostream &
operator << (ostream &out, const AnimInterface &ai) {
ai.output(out);
return out;
}

View File

@ -0,0 +1,379 @@
// Filename: animInterface.cxx
// Created by: drose (20Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "animInterface.h"
#include "clockObject.h"
TypeHandle AnimInterface::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
AnimInterface::
AnimInterface() :
_frame_rate(0.0),
_num_frames(0),
_play_mode(PM_pose),
_start_time(0.0),
_start_frame(0.0),
_play_frames(0.0),
_from_frame(0),
_to_frame(0),
_play_rate(1.0),
_effective_frame_rate(0.0),
_paused(true),
_paused_f(0.0)
{
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
AnimInterface::
AnimInterface(const AnimInterface &copy) :
_frame_rate(copy._frame_rate),
_num_frames(copy._num_frames),
_play_mode(copy._play_mode),
_start_time(copy._start_time),
_start_frame(copy._start_frame),
_play_frames(copy._play_frames),
_from_frame(copy._from_frame),
_to_frame(copy._to_frame),
_play_rate(copy._play_rate),
_effective_frame_rate(copy._effective_frame_rate),
_paused(copy._paused),
_paused_f(copy._paused_f)
{
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
AnimInterface::
~AnimInterface() {
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::play
// Access: Published
// Description: Runs the animation from the frame "from" to and
// including the frame "to", at which point the
// animation is stopped. Both "from" and "to" frame
// numbers may be outside the range (0,
// get_num_frames()) and the animation will follow the
// range correctly, reporting numbers modulo
// get_num_frames(). For instance, play(0,
// get_num_frames() * 2) will play the animation twice
// and then stop.
////////////////////////////////////////////////////////////////////
void AnimInterface::
play(double from, double to) {
if (from >= to) {
pose(from);
return;
}
_play_mode = PM_play;
_start_time = ClockObject::get_global_clock()->get_frame_time();
_start_frame = from;
_play_frames = to - from + 1.0;
_from_frame = (int)floor(from);
_to_frame = (int)floor(to);
_paused_f = 0.0;
if (_effective_frame_rate < 0.0) {
// If we'll be playing backward, start at the end.
_start_time -= _play_frames / _effective_frame_rate;
}
animation_activated();
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::loop
// Access: Published
// Description: Loops the animation from the frame "from" to and
// including the frame "to", indefinitely. If restart
// is true, the animation is restarted from the
// beginning; otherwise, it continues from the current
// frame.
////////////////////////////////////////////////////////////////////
void AnimInterface::
loop(bool restart, double from, double to) {
if (from >= to) {
pose(from);
return;
}
double fframe = get_full_fframe();
_play_mode = PM_loop;
_start_time = ClockObject::get_global_clock()->get_frame_time();
_start_frame = from;
_play_frames = to - from + 1.0;
_from_frame = (int)floor(from);
_to_frame = (int)floor(to);
_paused_f = 0.0;
if (!restart) {
if (_paused) {
_paused_f = fframe - _start_frame;
} else {
_start_time -= fframe / _effective_frame_rate;
}
}
animation_activated();
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::pingpong
// Access: Published
// Description: Loops the animation from the frame "from" to and
// including the frame "to", and then back in the
// opposite direction, indefinitely.
////////////////////////////////////////////////////////////////////
void AnimInterface::
pingpong(bool restart, double from, double to) {
if (from >= to) {
pose(from);
return;
}
double fframe = get_full_fframe();
_play_mode = PM_pingpong;
_start_time = ClockObject::get_global_clock()->get_frame_time();
_start_frame = from;
_play_frames = to - from + 1.0;
_from_frame = (int)floor(from);
_to_frame = (int)floor(to);
_paused_f = 0.0;
if (!restart) {
if (_paused) {
_paused_f = fframe - _start_frame;
} else {
_start_time -= fframe / _effective_frame_rate;
}
}
animation_activated();
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::pose
// Access: Published
// Description: Sets the animation to the indicated frame and holds
// it there.
////////////////////////////////////////////////////////////////////
void AnimInterface::
pose(int frame) {
_play_mode = PM_pose;
_start_time = ClockObject::get_global_clock()->get_frame_time();
_start_frame = (double)frame;
_play_frames = 0.0;
_from_frame = frame;
_to_frame = frame;
_paused_f = 0.0;
animation_activated();
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_full_frame
// Access: Published
// Description: Returns the current integer frame number.
//
// Unlike the value returned by get_frame(), this frame
// number may extend beyond the range of
// get_num_frames() if the frame range passed to play(),
// loop(), etc. did.
//
// Unlike the value returned by get_full_fframe(), this
// return value will never exceed the value passed to
// to_frame in the play() method.
////////////////////////////////////////////////////////////////////
int AnimInterface::
get_full_frame() const {
int frame = (int)floor(get_full_fframe());
if (_play_mode == PM_play) {
// In play mode, we never let the return value exceed
// (_from_frame, _to_frame).
frame = min(max(frame, _from_frame), _to_frame);
}
return frame;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_full_fframe
// Access: Published
// Description: Returns the current floating-point frame number.
//
// Unlike the value returned by get_frame(), this frame
// number may extend beyond the range of
// get_num_frames() if the frame range passed to play(),
// loop(), etc. did.
//
// Unlike the value returned by get_full_frame(), this
// return value may equal (to_frame + 1.0), when the
// animation has played to its natural end. However, in
// this case the return value of get_full_frame() will
// be to_frame, not (to_frame + 1).
////////////////////////////////////////////////////////////////////
double AnimInterface::
get_full_fframe() const {
switch (_play_mode) {
case PM_pose:
return _start_frame;
case PM_play:
return min(max(get_f(), 0.0), _play_frames) + _start_frame;
case PM_loop:
return cmod(get_f(), _play_frames) + _start_frame;
case PM_pingpong:
{
double f = cmod(get_f(), _play_frames * 2.0);
if (f > _play_frames) {
return (_play_frames * 2.0 - f) + _start_frame;
} else {
return f + _start_frame;
}
}
}
return _start_frame;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::is_playing
// Access: Published
// Description: Returns true if the animation is currently playing,
// false if it is stopped (e.g. because stop() or pose()
// was called, or because it reached the end of the
// animation after play() was called).
////////////////////////////////////////////////////////////////////
bool AnimInterface::
is_playing() const {
switch (_play_mode) {
case PM_pose:
return false;
case PM_play:
return get_f() < _play_frames;
case PM_loop:
case PM_pingpong:
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void AnimInterface::
output(ostream &out) const {
switch (_play_mode) {
case PM_pose:
out << "pose, frame " << get_frame();
return;
case PM_play:
out << "play, frame " << get_frame();
return;
case PM_loop:
out << "loop, frame " << get_frame();
return;
case PM_pingpong:
out << "pingpong, frame " << get_frame();
return;
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::animation_activated
// Access: Protected, Virtual
// Description: This is provided as a callback method for when the
// user calls one of the play/loop/pose type methods to
// start the animation playing.
////////////////////////////////////////////////////////////////////
void AnimInterface::
animation_activated() {
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::get_f
// Access: Private
// Description: Returns the current floating-point frame number,
// elapsed since _start_frame.
////////////////////////////////////////////////////////////////////
double AnimInterface::
get_f() const {
if (_paused) {
return _paused_f;
} else {
double now = ClockObject::get_global_clock()->get_frame_time();
double elapsed = now - _start_time;
return (elapsed * _effective_frame_rate);
}
}
////////////////////////////////////////////////////////////////////
// Function: AnimInterface::internal_set_rate
// Access: Private
// Description: Called internally to adjust either or both of the
// frame_rate or play_rate without changing the current
// frame number if the animation is already playing.
////////////////////////////////////////////////////////////////////
void AnimInterface::
internal_set_rate(double frame_rate, double play_rate) {
double f = get_f();
_frame_rate = frame_rate;
_play_rate = play_rate;
_effective_frame_rate = frame_rate * play_rate;
if (_effective_frame_rate == 0.0) {
_paused_f = f;
_paused = true;
} else {
// Compute a new _start_time that will keep f the same value with
// the new play_rate.
double new_elapsed = f / _effective_frame_rate;
double now = ClockObject::get_global_clock()->get_frame_time();
_start_time = now - new_elapsed;
_paused = false;
}
}

View File

@ -0,0 +1,111 @@
// Filename: animInterface.h
// Created by: drose (20Sep05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef ANIMINTERFACE_H
#define ANIMINTERFACE_H
#include "pandabase.h"
#include "typeHandle.h"
#include "register_type.h"
////////////////////////////////////////////////////////////////////
// Class : AnimInterface
// Description : This is the fundamental interface for things that
// have a play/loop/stop type interface for frame-based
// animation, such as animated characters. This is the
// base class for AnimControl and other, similar
// classes.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AnimInterface {
protected:
AnimInterface();
AnimInterface(const AnimInterface &copy);
PUBLISHED:
virtual ~AnimInterface();
INLINE void play();
void play(double from, double to);
INLINE void loop(bool restart);
void loop(bool restart, double from, double to);
INLINE void pingpong(bool restart);
void pingpong(bool restart, double from, double to);
INLINE void stop();
void pose(int frame);
INLINE void set_play_rate(double play_rate);
INLINE double get_play_rate() const;
INLINE double get_frame_rate() const;
INLINE int get_num_frames() const;
INLINE int get_frame() const;
INLINE double get_frac() const;
int get_full_frame() const;
double get_full_fframe() const;
bool is_playing() const;
virtual void output(ostream &out) const;
protected:
INLINE void set_frame_rate(double frame_rate);
INLINE void set_num_frames(int num_frames);
virtual void animation_activated();
private:
double get_f() const;
void internal_set_rate(double frame_rate, double play_rate);
private:
enum PlayMode {
PM_pose,
PM_play,
PM_loop,
PM_pingpong,
};
double _frame_rate;
int _num_frames;
PlayMode _play_mode;
double _start_time;
double _start_frame;
double _play_frames;
int _from_frame;
int _to_frame;
double _play_rate;
double _effective_frame_rate;
bool _paused;
double _paused_f;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "AnimInterface");
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const AnimInterface &ai);
#include "animInterface.I"
#endif

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "config_util.h"
#include "animInterface.h"
#include "bamReaderParam.h"
#include "cachedTypedWritableReferenceCount.h"
#include "clockObject.h"
@ -67,6 +68,7 @@ ConfigVariableSearchPath sound_path
PRC_DESC("The directories to search for sound and music files to be loaded."));
ConfigureFn(config_util) {
AnimInterface::init_type();
BamReaderParam::init_type();
CachedTypedWritableReferenceCount::init_type();
Configurable::init_type();

Some files were not shown because too many files have changed in this diff Show More