Merge branch 'master' into interrogate-overhaul
Conflicts: dtool/src/cppparser/cppBison.yxx dtool/src/interrogate/interfaceMakerPythonNative.cxx
|
|
@ -1,4 +1,3 @@
|
|||
/built_x64
|
||||
/built
|
||||
/samples
|
||||
/thirdparty
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
static const float _PI = 3.14;
|
||||
|
||||
AIBehaviors::AIBehaviors() {
|
||||
_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_behaviors_flags = _behaviors_flags & _none;
|
||||
_previous_conflict = false;
|
||||
_conflict = false;
|
||||
|
|
@ -67,7 +67,7 @@ bool AIBehaviors::is_conflict() {
|
|||
}
|
||||
|
||||
if(is_on(_flee)) {
|
||||
LVecBase3f dirn = _flee_force;
|
||||
LVecBase3 dirn = _flee_force;
|
||||
dirn.normalize();
|
||||
_flee_force = _steering_force.length() * dirn * _flee_obj->_flee_weight;
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ bool AIBehaviors::is_conflict() {
|
|||
}
|
||||
|
||||
if(is_on(_evade)) {
|
||||
LVecBase3f dirn = _evade_force;
|
||||
LVecBase3 dirn = _evade_force;
|
||||
dirn.normalize();
|
||||
_evade_force = _steering_force.length() * dirn * _evade_obj->_evade_weight;
|
||||
}
|
||||
|
|
@ -111,9 +111,9 @@ bool AIBehaviors::is_conflict() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AIBehaviors::accumulate_force(string force_type, LVecBase3f force) {
|
||||
void AIBehaviors::accumulate_force(string force_type, LVecBase3 force) {
|
||||
|
||||
LVecBase3f old_force;
|
||||
LVecBase3 old_force;
|
||||
|
||||
if(force_type == "seek") {
|
||||
old_force = _seek_force;
|
||||
|
|
@ -169,8 +169,8 @@ void AIBehaviors::accumulate_force(string force_type, LVecBase3f force) {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f AIBehaviors::calculate_prioritized() {
|
||||
LVecBase3f force;
|
||||
LVecBase3 AIBehaviors::calculate_prioritized() {
|
||||
LVecBase3 force;
|
||||
|
||||
if(is_on(_seek)) {
|
||||
if(_conflict) {
|
||||
|
|
@ -299,13 +299,13 @@ LVecBase3f AIBehaviors::calculate_prioritized() {
|
|||
|
||||
if(is_on(_arrival)) {
|
||||
if(_seek_obj != NULL) {
|
||||
LVecBase3f dirn = _steering_force;
|
||||
LVecBase3 dirn = _steering_force;
|
||||
dirn.normalize();
|
||||
_steering_force = ((_steering_force.length() - _arrival_force.length()) * dirn);
|
||||
}
|
||||
|
||||
if(_pursue_obj != NULL) {
|
||||
LVecBase3f dirn = _steering_force;
|
||||
LVecBase3 dirn = _steering_force;
|
||||
dirn.normalize();
|
||||
_steering_force = ((_steering_force.length() - _arrival_force.length()) * _arrival_obj->_arrival_direction);
|
||||
}
|
||||
|
|
@ -639,7 +639,7 @@ void AIBehaviors::resume_ai(string ai_type) {
|
|||
// Function : seek
|
||||
// Description : This function activates seek and makes an object of the Seek class.
|
||||
// This is the function we want the user to call for seek to be done.
|
||||
// This function is overloaded to accept a NodePath or an LVecBase3f.
|
||||
// This function is overloaded to accept a NodePath or an LVecBase3.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -648,7 +648,7 @@ void AIBehaviors::seek(NodePath target_object, float seek_wt) {
|
|||
turn_on("seek");
|
||||
}
|
||||
|
||||
void AIBehaviors::seek(LVecBase3f pos, float seek_wt) {
|
||||
void AIBehaviors::seek(LVecBase3 pos, float seek_wt) {
|
||||
_seek_obj = new Seek(_ai_char, pos, seek_wt);
|
||||
turn_on("seek");
|
||||
}
|
||||
|
|
@ -657,7 +657,7 @@ void AIBehaviors::seek(LVecBase3f pos, float seek_wt) {
|
|||
//
|
||||
// Function : flee
|
||||
// Description : This function activates flee_activate and creates an object of the Flee class.
|
||||
// This function is overloaded to accept a NodePath or an LVecBase3f.
|
||||
// This function is overloaded to accept a NodePath or an LVecBase3.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -668,7 +668,7 @@ void AIBehaviors::flee(NodePath target_object, double panic_distance, double rel
|
|||
turn_on("flee_activate");
|
||||
}
|
||||
|
||||
void AIBehaviors::flee(LVecBase3f pos, double panic_distance, double relax_distance, float flee_wt) {
|
||||
void AIBehaviors::flee(LVecBase3 pos, double panic_distance, double relax_distance, float flee_wt) {
|
||||
_flee_obj = new Flee(_ai_char, pos, panic_distance, relax_distance, flee_wt);
|
||||
_flee_list.insert(_flee_list.end(), *_flee_obj);
|
||||
|
||||
|
|
@ -769,38 +769,38 @@ void AIBehaviors::flock_activate() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f AIBehaviors::do_flock() {
|
||||
LVecBase3 AIBehaviors::do_flock() {
|
||||
|
||||
//! Initialize variables required to compute the flocking force on the ai char.
|
||||
unsigned int neighbor_count = 0;
|
||||
LVecBase3f separation_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f alignment_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f cohesion_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f avg_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f total_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f avg_center_of_mass = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3f total_center_of_mass = LVecBase3f(0.0, 0.0, 0.0);
|
||||
LVecBase3 separation_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 alignment_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 cohesion_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 avg_neighbor_heading = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 total_neighbor_heading = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 avg_center_of_mass = LVecBase3(0.0, 0.0, 0.0);
|
||||
LVecBase3 total_center_of_mass = LVecBase3(0.0, 0.0, 0.0);
|
||||
|
||||
//! Loop through all the other AI units in the flock to check if they are neigbours.
|
||||
for(unsigned int i = 0; i < _flock_group->_ai_char_list.size(); i++) {
|
||||
if(_flock_group->_ai_char_list[i]->_name != _ai_char->_name) {
|
||||
|
||||
//! Using visibilty cone to detect neighbors.
|
||||
LVecBase3f dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.get_pos();
|
||||
LVecBase3f ai_char_heading = _ai_char->get_velocity();
|
||||
LVecBase3 dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.get_pos();
|
||||
LVecBase3 ai_char_heading = _ai_char->get_velocity();
|
||||
ai_char_heading.normalize();
|
||||
|
||||
//! Check if the current unit is a neighbor.
|
||||
if(dist_vect.dot(ai_char_heading) > ((dist_vect.length()) * (ai_char_heading.length()) * cos(_flock_group->_flock_vcone_angle * (_PI / 180)))
|
||||
&& (dist_vect.length() < _flock_group->_flock_vcone_radius)) {
|
||||
//! Separation force calculation.
|
||||
LVecBase3f ai_char_to_units = _ai_char->_ai_char_np.get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
|
||||
LVecBase3 ai_char_to_units = _ai_char->_ai_char_np.get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
|
||||
float to_units_dist = ai_char_to_units.length();
|
||||
ai_char_to_units.normalize();
|
||||
separation_force += (ai_char_to_units / to_units_dist);
|
||||
|
||||
//! Calculating the total heading and center of mass of all the neighbors.
|
||||
LVecBase3f neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity();
|
||||
LVecBase3 neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity();
|
||||
neighbor_heading.normalize();
|
||||
total_neighbor_heading += neighbor_heading;
|
||||
total_center_of_mass += _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
|
||||
|
|
@ -814,7 +814,7 @@ LVecBase3f AIBehaviors::do_flock() {
|
|||
if(neighbor_count > 0) {
|
||||
//! Alignment force calculation
|
||||
avg_neighbor_heading = total_neighbor_heading / neighbor_count;
|
||||
LVector3f ai_char_heading = _ai_char->get_velocity();
|
||||
LVector3 ai_char_heading = _ai_char->get_velocity();
|
||||
ai_char_heading.normalize();
|
||||
avg_neighbor_heading -= ai_char_heading;
|
||||
avg_neighbor_heading.normalize();
|
||||
|
|
@ -822,7 +822,7 @@ LVecBase3f AIBehaviors::do_flock() {
|
|||
|
||||
//! Cohesion force calculation
|
||||
avg_center_of_mass = total_center_of_mass / neighbor_count;
|
||||
LVecBase3f cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.get_pos();
|
||||
LVecBase3 cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.get_pos();
|
||||
cohesion_dir.normalize();
|
||||
cohesion_force = cohesion_dir * _ai_char->_movt_force;
|
||||
}
|
||||
|
|
@ -830,7 +830,7 @@ LVecBase3f AIBehaviors::do_flock() {
|
|||
_flock_done = true;
|
||||
turn_off("flock");
|
||||
turn_on("flock_activate");
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
//! Calculate the resultant force on the ai character by taking into account the separation, alignment and cohesion
|
||||
|
|
@ -885,7 +885,7 @@ void AIBehaviors::path_follow(float follow_wt) {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AIBehaviors::add_to_path(LVecBase3f pos) {
|
||||
void AIBehaviors::add_to_path(LVecBase3 pos) {
|
||||
_path_follow_obj->add_to_path(pos);
|
||||
}
|
||||
|
||||
|
|
@ -923,7 +923,7 @@ void AIBehaviors::init_path_find(const char* navmesh_filename) {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AIBehaviors::path_find_to(LVecBase3f pos, string type) {
|
||||
void AIBehaviors::path_find_to(LVecBase3 pos, string type) {
|
||||
_path_find_obj->path_find(pos, type);
|
||||
}
|
||||
|
||||
|
|
@ -1331,56 +1331,56 @@ switch(char_to_int(ai_type)) {
|
|||
if (is_on(_seek)) {
|
||||
_behaviors_flags ^= _seek;
|
||||
}
|
||||
_seek_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_seek_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (is_on(_flee)) {
|
||||
_behaviors_flags ^= _flee;
|
||||
}
|
||||
_flee_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_flee_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
if(is_on(_pursue)) {
|
||||
_behaviors_flags ^= _pursue;
|
||||
}
|
||||
_pursue_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_pursue_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
if(is_on(_evade)) {
|
||||
_behaviors_flags ^= _evade;
|
||||
}
|
||||
_evade_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_evade_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
if (is_on(_arrival)) {
|
||||
_behaviors_flags ^= _arrival;
|
||||
}
|
||||
_arrival_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_arrival_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
if(is_on(_flock)) {
|
||||
_behaviors_flags ^= _flock;
|
||||
}
|
||||
_flock_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_flock_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
if(is_on(_wander)) {
|
||||
_behaviors_flags ^= _wander;
|
||||
}
|
||||
_wander_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_wander_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
if(is_on(_obstacle_avoidance)) {
|
||||
_behaviors_flags ^= _obstacle_avoidance;
|
||||
}
|
||||
_obstacle_avoidance_force = LVecBase3f(0.0f, 0.0f, 0.0f);
|
||||
_obstacle_avoidance_force = LVecBase3(0.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case 9:{
|
||||
|
|
|
|||
|
|
@ -73,41 +73,41 @@ public:
|
|||
Flock *_flock_group;
|
||||
|
||||
int _behaviors_flags;
|
||||
LVecBase3f _steering_force;
|
||||
LVecBase3 _steering_force;
|
||||
|
||||
Seek *_seek_obj;
|
||||
LVecBase3f _seek_force;
|
||||
LVecBase3 _seek_force;
|
||||
|
||||
Flee *_flee_obj;
|
||||
LVecBase3f _flee_force;
|
||||
LVecBase3 _flee_force;
|
||||
|
||||
//! This list is used if the ai character needs to flee from multiple onjects.
|
||||
ListFlee _flee_list;
|
||||
ListFlee::iterator _flee_itr;
|
||||
|
||||
Pursue *_pursue_obj;
|
||||
LVecBase3f _pursue_force;
|
||||
LVecBase3 _pursue_force;
|
||||
|
||||
Evade *_evade_obj;
|
||||
LVecBase3f _evade_force;
|
||||
LVecBase3 _evade_force;
|
||||
|
||||
//! This list is used if the ai character needs to evade from multiple onjects.
|
||||
ListEvade _evade_list;
|
||||
ListEvade::iterator _evade_itr;
|
||||
|
||||
Arrival *_arrival_obj;
|
||||
LVecBase3f _arrival_force;
|
||||
LVecBase3 _arrival_force;
|
||||
|
||||
//! Since Flock is a collective behavior the variables are declared within the AIBehaviors class.
|
||||
float _flock_weight;
|
||||
LVecBase3f _flock_force;
|
||||
LVecBase3 _flock_force;
|
||||
bool _flock_done;
|
||||
|
||||
Wander * _wander_obj;
|
||||
LVecBase3f _wander_force;
|
||||
LVecBase3 _wander_force;
|
||||
|
||||
ObstacleAvoidance *_obstacle_avoidance_obj;
|
||||
LVecBase3f _obstacle_avoidance_force;
|
||||
LVecBase3 _obstacle_avoidance_force;
|
||||
|
||||
PathFollow *_path_follow_obj;
|
||||
|
||||
|
|
@ -127,20 +127,20 @@ public:
|
|||
|
||||
bool is_conflict();
|
||||
|
||||
void accumulate_force(string force_type, LVecBase3f force);
|
||||
LVecBase3f calculate_prioritized();
|
||||
void accumulate_force(string force_type, LVecBase3 force);
|
||||
LVecBase3 calculate_prioritized();
|
||||
|
||||
void flock_activate();
|
||||
LVecBase3f do_flock();
|
||||
LVecBase3 do_flock();
|
||||
|
||||
int char_to_int(string ai_type);
|
||||
|
||||
PUBLISHED:
|
||||
void seek(NodePath target_object, float seek_wt = 1.0);
|
||||
void seek(LVecBase3f pos, float seek_wt = 1.0);
|
||||
void seek(LVecBase3 pos, float seek_wt = 1.0);
|
||||
|
||||
void flee(NodePath target_object, double panic_distance = 10.0, double relax_distance = 10.0, float flee_wt = 1.0);
|
||||
void flee(LVecBase3f pos, double panic_distance = 10.0, double relax_distance = 10.0, float flee_wt = 1.0);
|
||||
void flee(LVecBase3 pos, double panic_distance = 10.0, double relax_distance = 10.0, float flee_wt = 1.0);
|
||||
|
||||
void pursue(NodePath target_object, float pursue_wt = 1.0);
|
||||
|
||||
|
|
@ -155,12 +155,12 @@ PUBLISHED:
|
|||
void obstacle_avoidance(float feeler_length = 1.0);
|
||||
|
||||
void path_follow(float follow_wt);
|
||||
void add_to_path(LVecBase3f pos);
|
||||
void add_to_path(LVecBase3 pos);
|
||||
void start_follow(string type = "normal");
|
||||
|
||||
// should have different function names.
|
||||
void init_path_find(const char* navmesh_filename);
|
||||
void path_find_to(LVecBase3f pos, string type = "normal");
|
||||
void path_find_to(LVecBase3 pos, string type = "normal");
|
||||
void path_find_to(NodePath target, string type = "normal");
|
||||
void add_static_obstacle(NodePath obstacle);
|
||||
void add_dynamic_obstacle(NodePath obstacle);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ AICharacter::AICharacter(string model_name, NodePath model_np, double mass, doub
|
|||
_max_force = max_force;
|
||||
_movt_force = movt_force;
|
||||
|
||||
_velocity = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_velocity = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
|
||||
_steering = new AIBehaviors();
|
||||
_steering->_ai_char = this;
|
||||
|
|
@ -43,48 +43,43 @@ AICharacter::~AICharacter() {
|
|||
// This also makes the character look at the direction of the force.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AICharacter::update() {
|
||||
|
||||
if(!_steering->is_off(_steering->_none)) {
|
||||
|
||||
LVecBase3f old_pos = _ai_char_np.get_pos();
|
||||
|
||||
LVecBase3f steering_force = _steering->calculate_prioritized();
|
||||
|
||||
LVecBase3f acceleration = steering_force / _mass;
|
||||
void AICharacter::
|
||||
update() {
|
||||
if (!_steering->is_off(_steering->_none)) {
|
||||
LVecBase3 old_pos = _ai_char_np.get_pos();
|
||||
LVecBase3 steering_force = _steering->calculate_prioritized();
|
||||
LVecBase3 acceleration = steering_force / _mass;
|
||||
|
||||
_velocity = acceleration;
|
||||
|
||||
LVecBase3f direction = _steering->_steering_force;
|
||||
LVecBase3 direction = _steering->_steering_force;
|
||||
direction.normalize();
|
||||
|
||||
_ai_char_np.set_pos(old_pos + _velocity) ;
|
||||
|
||||
if(steering_force.length() > 0) {
|
||||
if (steering_force.length() > 0) {
|
||||
_ai_char_np.look_at(old_pos + (direction * 5));
|
||||
_ai_char_np.set_h(_ai_char_np.get_h() + 180);
|
||||
_ai_char_np.set_p(-_ai_char_np.get_p());
|
||||
_ai_char_np.set_r(-_ai_char_np.get_r());
|
||||
}
|
||||
}
|
||||
else {
|
||||
_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_seek_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_flee_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_pursue_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_evade_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_arrival_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_flock_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_steering->_wander_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
} else {
|
||||
_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_seek_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_flee_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_pursue_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_evade_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_arrival_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_flock_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_steering->_wander_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
LVecBase3f AICharacter::get_velocity() {
|
||||
LVecBase3 AICharacter::get_velocity() {
|
||||
return _velocity;
|
||||
}
|
||||
|
||||
void AICharacter::set_velocity(LVecBase3f velocity) {
|
||||
void AICharacter::set_velocity(LVecBase3 velocity) {
|
||||
_velocity = velocity;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ class EXPCL_PANDAAI AICharacter {
|
|||
public:
|
||||
double _mass;
|
||||
double _max_force;
|
||||
LVecBase3f _velocity;
|
||||
LVecBase3f _steering_force;
|
||||
LVecBase3 _velocity;
|
||||
LVecBase3 _steering_force;
|
||||
string _name;
|
||||
double _movt_force;
|
||||
unsigned int _ai_char_flock_id;
|
||||
|
|
@ -51,7 +51,7 @@ class EXPCL_PANDAAI AICharacter {
|
|||
bool _pf_guide;
|
||||
|
||||
void update();
|
||||
void set_velocity(LVecBase3f vel);
|
||||
void set_velocity(LVecBase3 vel);
|
||||
void set_char_render(NodePath render);
|
||||
NodePath get_char_render();
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ PUBLISHED:
|
|||
double get_mass();
|
||||
void set_mass(double m);
|
||||
|
||||
LVecBase3f get_velocity();
|
||||
LVecBase3 get_velocity();
|
||||
|
||||
double get_max_force();
|
||||
void set_max_force(double max_force);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "aiNode.h"
|
||||
|
||||
AINode::AINode(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h) {
|
||||
AINode::AINode(int grid_x, int grid_y, LVecBase3 pos, float w, float l, float h) {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_neighbours[i] = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public:
|
|||
int _grid_x, _grid_y;
|
||||
|
||||
// Position of the node in 3D space.
|
||||
LVecBase3f _position;
|
||||
LVecBase3 _position;
|
||||
|
||||
// Dimensions of each face / cell on the mesh.
|
||||
// Height is given in case of expansion to a 3d mesh. Currently
|
||||
|
|
@ -77,7 +77,7 @@ public:
|
|||
AINode *_next;
|
||||
|
||||
PUBLISHED:
|
||||
AINode(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h);
|
||||
AINode(int grid_x, int grid_y, LVecBase3 pos, float w, float l, float h);
|
||||
~AINode();
|
||||
|
||||
bool contains(float x, float y);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ void PathFinder::find_path(Node *src_node, Node *dest_node) {
|
|||
|
||||
// Add a dummy node as the first element of the open list with score = -1.
|
||||
// Inorder to implement a binary heap the index of the elements should never be 0.
|
||||
Node *_dummy_node = new Node(-1, -1, LVecBase3f(0.0, 0.0, 0.0), 0, 0, 0);
|
||||
Node *_dummy_node = new Node(-1, -1, LVecBase3(0.0, 0.0, 0.0), 0, 0, 0);
|
||||
_dummy_node->_status = _dummy_node->open;
|
||||
_dummy_node->_score = -1;
|
||||
_open_list.push_back(_dummy_node);
|
||||
|
|
@ -379,7 +379,7 @@ void PathFinder::remove_from_clist(int r, int c) {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Node* find_in_mesh(NavMesh nav_mesh, LVecBase3f pos, int grid_size) {
|
||||
Node* find_in_mesh(NavMesh nav_mesh, LVecBase3 pos, int grid_size) {
|
||||
int size = grid_size;
|
||||
float x = pos[0];
|
||||
float y = pos[1];
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
typedef vector<Node *> NodeArray;
|
||||
typedef vector<NodeArray> NavMesh;
|
||||
|
||||
Node* find_in_mesh(NavMesh nav_mesh, LVecBase3f pos, int grid_size);
|
||||
Node* find_in_mesh(NavMesh nav_mesh, LVecBase3 pos, int grid_size);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ Arrival::~Arrival() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Arrival::do_arrival() {
|
||||
LVecBase3f direction_to_target;
|
||||
LVecBase3 Arrival::do_arrival() {
|
||||
LVecBase3 direction_to_target;
|
||||
double distance;
|
||||
|
||||
if(_arrival_type) {
|
||||
|
|
@ -52,22 +52,22 @@ LVecBase3f Arrival::do_arrival() {
|
|||
_arrival_direction.normalize();
|
||||
|
||||
if(int(distance) == 0) {
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_arrival_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_arrival_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
|
||||
if(_ai_char->_steering->_seek_obj != NULL) {
|
||||
_ai_char->_steering->turn_off("arrival");
|
||||
_ai_char->_steering->turn_on("arrival_activate");
|
||||
}
|
||||
_arrival_done = true;
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
_arrival_done = false;
|
||||
}
|
||||
|
||||
double u = _ai_char->get_velocity().length();
|
||||
LVecBase3f desired_force = ((u * u) / (2 * distance)) * _ai_char->get_mass();
|
||||
LVecBase3 desired_force = ((u * u) / (2 * distance)) * _ai_char->get_mass();
|
||||
|
||||
if(_ai_char->_steering->_seek_obj != NULL) {
|
||||
return(desired_force);
|
||||
|
|
@ -85,7 +85,7 @@ LVecBase3f Arrival::do_arrival() {
|
|||
}
|
||||
|
||||
cout<<"Arrival works only with seek and pursue"<<endl;
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -98,7 +98,7 @@ LVecBase3f Arrival::do_arrival() {
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Arrival::arrival_activate() {
|
||||
LVecBase3f dirn;
|
||||
LVecBase3 dirn;
|
||||
if(_arrival_type) {
|
||||
dirn = (_ai_char->_ai_char_np.get_pos(_ai_char->_window_render) - _ai_char->get_ai_behaviors()->_pursue_obj->_pursue_target.get_pos(_ai_char->_window_render));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ public:
|
|||
AICharacter *_ai_char;
|
||||
|
||||
NodePath _arrival_target;
|
||||
LVecBase3f _arrival_target_pos;
|
||||
LVecBase3 _arrival_target_pos;
|
||||
double _arrival_distance;
|
||||
LVecBase3f _arrival_direction;
|
||||
LVecBase3 _arrival_direction;
|
||||
bool _arrival_done;
|
||||
|
||||
// This flag specifies if the arrival behavior is being used with seek or pursue behavior.
|
||||
|
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
Arrival(AICharacter *ai_ch, double distance = 10.0);
|
||||
~Arrival();
|
||||
LVecBase3f do_arrival();
|
||||
LVecBase3 do_arrival();
|
||||
void arrival_activate();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,23 +42,23 @@ Evade::~Evade() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Evade::do_evade() {
|
||||
LVecBase3 Evade::do_evade() {
|
||||
assert(_evade_target && "evade target not assigned");
|
||||
|
||||
_evade_direction = _ai_char->_ai_char_np.get_pos(_ai_char->_window_render) - _evade_target.get_pos(_ai_char->_window_render);
|
||||
double distance = _evade_direction.length();
|
||||
|
||||
_evade_direction.normalize();
|
||||
LVecBase3f desired_force = _evade_direction * _ai_char->_movt_force;
|
||||
LVecBase3 desired_force = _evade_direction * _ai_char->_movt_force;
|
||||
|
||||
if(distance > (_evade_distance + _evade_relax_distance)) {
|
||||
if((_ai_char->_steering->_behaviors_flags | _ai_char->_steering->_evade) == _ai_char->_steering->_evade) {
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
}
|
||||
_ai_char->_steering->turn_off("evade");
|
||||
_ai_char->_steering->turn_on("evade_activate");
|
||||
_evade_done = true;
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
_evade_done = false;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
NodePath _evade_target;
|
||||
float _evade_weight;
|
||||
LVecBase3f _evade_direction;
|
||||
LVecBase3 _evade_direction;
|
||||
double _evade_distance;
|
||||
double _evade_relax_distance;
|
||||
bool _evade_done;
|
||||
|
|
@ -38,7 +38,7 @@ public:
|
|||
double relax_distance, float evade_wt);
|
||||
|
||||
~Evade();
|
||||
LVecBase3f do_evade();
|
||||
LVecBase3 do_evade();
|
||||
void evade_activate();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Flee::Flee(AICharacter *ai_ch, NodePath target_object, double panic_distance,
|
|||
_flee_activate_done = false;
|
||||
}
|
||||
|
||||
Flee::Flee(AICharacter *ai_ch, LVecBase3f pos, double panic_distance,
|
||||
Flee::Flee(AICharacter *ai_ch, LVecBase3 pos, double panic_distance,
|
||||
double relax_distance, float flee_wt){
|
||||
|
||||
_ai_char = ai_ch;
|
||||
|
|
@ -57,10 +57,10 @@ Flee::~Flee() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Flee::do_flee() {
|
||||
LVecBase3f dirn;
|
||||
LVecBase3 Flee::do_flee() {
|
||||
LVecBase3 dirn;
|
||||
double distance;
|
||||
LVecBase3f desired_force;
|
||||
LVecBase3 desired_force;
|
||||
|
||||
dirn = _ai_char->_ai_char_np.get_pos(_ai_char->_window_render) - _flee_present_pos;
|
||||
distance = dirn.length();
|
||||
|
|
@ -68,12 +68,12 @@ LVecBase3f Flee::do_flee() {
|
|||
|
||||
if(distance > (_flee_distance + _flee_relax_distance)) {
|
||||
if((_ai_char->_steering->_behaviors_flags | _ai_char->_steering->_flee) == _ai_char->_steering->_flee) {
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
}
|
||||
_flee_done = true;
|
||||
_ai_char->_steering->turn_off("flee");
|
||||
_ai_char->_steering->turn_on("flee_activate");
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
return(desired_force);
|
||||
|
|
@ -90,7 +90,7 @@ LVecBase3f Flee::do_flee() {
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Flee::flee_activate() {
|
||||
LVecBase3f dirn;
|
||||
LVecBase3 dirn;
|
||||
double distance;
|
||||
|
||||
_flee_activate_done = false;
|
||||
|
|
|
|||
|
|
@ -26,23 +26,23 @@ class EXPCL_PANDAAI Flee {
|
|||
public:
|
||||
AICharacter *_ai_char;
|
||||
|
||||
LVecBase3f _flee_position;
|
||||
LVecBase3 _flee_position;
|
||||
float _flee_weight;
|
||||
LVecBase3f _flee_direction;
|
||||
LVecBase3 _flee_direction;
|
||||
double _flee_distance;
|
||||
double _flee_relax_distance;
|
||||
LVecBase3f _flee_present_pos;
|
||||
LVecBase3 _flee_present_pos;
|
||||
bool _flee_done;
|
||||
bool _flee_activate_done;
|
||||
|
||||
Flee(AICharacter *ai_ch, NodePath target_object, double panic_distance = 10.0,
|
||||
double relax_distance = 10.0, float flee_wt = 1.0);
|
||||
|
||||
Flee(AICharacter *ai_ch, LVecBase3f pos, double panic_distance = 10.0,
|
||||
Flee(AICharacter *ai_ch, LVecBase3 pos, double panic_distance = 10.0,
|
||||
double relax_distance = 10.0, float flee_wt = 1.0);
|
||||
|
||||
~Flee();
|
||||
LVecBase3f do_flee();
|
||||
LVecBase3 do_flee();
|
||||
void flee_activate();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#include "meshNode.h"
|
||||
|
||||
Node::Node(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h) {
|
||||
Node::Node(int grid_x, int grid_y, LVecBase3 pos, float w, float l, float h) {
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
_neighbours[i] = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public:
|
|||
int _grid_x, _grid_y;
|
||||
|
||||
// Position of the node in 3D space.
|
||||
LVecBase3f _position;
|
||||
LVecBase3 _position;
|
||||
|
||||
// Dimensions of each face / cell on the mesh.
|
||||
// Height is given in case of expansion to a 3d mesh. Currently not used.
|
||||
|
|
@ -58,7 +58,7 @@ public:
|
|||
// Note: The data in this member is discarded when mesh data is written into navmesh.csv file.
|
||||
Node *_next;
|
||||
|
||||
Node(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h);
|
||||
Node(int grid_x, int grid_y, LVecBase3 pos, float w, float l, float h);
|
||||
~Node();
|
||||
|
||||
bool contains(float x, float y);
|
||||
|
|
|
|||
|
|
@ -35,15 +35,15 @@ bool ObstacleAvoidance::obstacle_detection() {
|
|||
// Calculate the volume of the AICharacter with respect to render
|
||||
PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
|
||||
CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
|
||||
LVecBase3f avoidance(0.0, 0.0, 0.0);
|
||||
LVecBase3 avoidance(0.0, 0.0, 0.0);
|
||||
double distance = 0x7fff ;
|
||||
double expanded_radius;
|
||||
LVecBase3f to_obstacle;
|
||||
LVecBase3f prev_avoidance;
|
||||
LVecBase3 to_obstacle;
|
||||
LVecBase3 prev_avoidance;
|
||||
for(unsigned int i = 0; i < _ai_char->_world->_obstacles.size(); ++i) {
|
||||
PT(BoundingVolume) bounds = _ai_char->_world->_obstacles[i].get_bounds();
|
||||
CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
|
||||
LVecBase3f near_obstacle = _ai_char->_world->_obstacles[i].get_pos() - _ai_char->get_node_path().get_pos();
|
||||
LVecBase3 near_obstacle = _ai_char->_world->_obstacles[i].get_pos() - _ai_char->get_node_path().get_pos();
|
||||
// Check if it's the nearest obstacle, If so initialize as the nearest obstacle
|
||||
if((near_obstacle.length() < distance) && (_ai_char->_world->_obstacles[i].get_pos() != _ai_char->get_node_path().get_pos())) {
|
||||
_nearest_obstacle = _ai_char->_world->_obstacles[i];
|
||||
|
|
@ -51,13 +51,13 @@ bool ObstacleAvoidance::obstacle_detection() {
|
|||
expanded_radius = bsphere->get_radius() + np_sphere->get_radius();
|
||||
}
|
||||
}
|
||||
LVecBase3f feeler = _feeler * _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3f::forward());
|
||||
LVecBase3 feeler = _feeler * _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
|
||||
feeler.normalize();
|
||||
feeler *= (expanded_radius + np_sphere->get_radius()) ;
|
||||
to_obstacle = _nearest_obstacle.get_pos() - _ai_char->get_node_path().get_pos();
|
||||
LVector3f line_vector = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3f::forward());
|
||||
LVecBase3f project = (to_obstacle.dot(line_vector) * line_vector) / line_vector.length_squared();
|
||||
LVecBase3f perp = project - to_obstacle;
|
||||
LVector3 line_vector = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
|
||||
LVecBase3 project = (to_obstacle.dot(line_vector) * line_vector) / line_vector.length_squared();
|
||||
LVecBase3 perp = project - to_obstacle;
|
||||
// If the nearest obstacle will collide with our AICharacter then send obstacle detection as true
|
||||
if((_nearest_obstacle) && (perp.length() < expanded_radius - np_sphere->get_radius()) && (project.length() < feeler.length())) {
|
||||
return true;
|
||||
|
|
@ -90,27 +90,27 @@ void ObstacleAvoidance::obstacle_avoidance_activate() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f ObstacleAvoidance::do_obstacle_avoidance() {
|
||||
LVecBase3f offset = _ai_char->get_node_path().get_pos() - _nearest_obstacle.get_pos();
|
||||
LVecBase3 ObstacleAvoidance::do_obstacle_avoidance() {
|
||||
LVecBase3 offset = _ai_char->get_node_path().get_pos() - _nearest_obstacle.get_pos();
|
||||
PT(BoundingVolume) bounds =_nearest_obstacle.get_bounds();
|
||||
CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
|
||||
PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
|
||||
CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
|
||||
double distance_needed = offset.length() - bsphere->get_radius() - np_sphere->get_radius();
|
||||
if((obstacle_detection())) {
|
||||
LVecBase3f direction = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3f::forward());
|
||||
LVecBase3 direction = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
|
||||
direction.normalize();
|
||||
float forward_component = offset.dot(direction);
|
||||
LVecBase3f projection = forward_component * direction;
|
||||
LVecBase3f perpendicular_component = offset - projection;
|
||||
LVecBase3 projection = forward_component * direction;
|
||||
LVecBase3 perpendicular_component = offset - projection;
|
||||
double p = perpendicular_component.length();
|
||||
perpendicular_component.normalize();
|
||||
LVecBase3f avoidance = perpendicular_component;
|
||||
LVecBase3 avoidance = perpendicular_component;
|
||||
// The more closer the obstacle, the more force it generates
|
||||
avoidance = (avoidance * _ai_char->get_max_force() * _ai_char->_movt_force) / (p + 0.01);
|
||||
return avoidance;
|
||||
}
|
||||
_ai_char->_steering->turn_on("obstacle_avoidance_activate");
|
||||
_ai_char->_steering->turn_off("obstacle_avoidance");
|
||||
return LVecBase3f(0, 0, 0);
|
||||
return LVecBase3(0, 0, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class EXPCL_PANDAAI ObstacleAvoidance {
|
|||
float _feeler;
|
||||
|
||||
ObstacleAvoidance(AICharacter *ai_char, float feeler_length);
|
||||
LVecBase3f do_obstacle_avoidance();
|
||||
LVecBase3 do_obstacle_avoidance();
|
||||
~ObstacleAvoidance();
|
||||
void obstacle_avoidance_activate();
|
||||
bool obstacle_detection();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ void PathFind::create_nav_mesh(const char* navmesh_filename) {
|
|||
// Stage variables.
|
||||
int grid_x, grid_y;
|
||||
float l, w, h;
|
||||
LVecBase3f position;
|
||||
LVecBase3 position;
|
||||
|
||||
// Variable to hold line data read from file.
|
||||
string line;
|
||||
|
|
@ -75,7 +75,7 @@ void PathFind::create_nav_mesh(const char* navmesh_filename) {
|
|||
l = atof(fields[4].c_str());
|
||||
w = atof(fields[5].c_str());
|
||||
h = atof(fields[6].c_str());
|
||||
position = LVecBase3f(atof(fields[7].c_str()), atof(fields[8].c_str()), atof(fields[9].c_str()));
|
||||
position = LVecBase3(atof(fields[7].c_str()), atof(fields[8].c_str()), atof(fields[9].c_str()));
|
||||
|
||||
Node *stage_node = new Node(grid_x, grid_y, position, w, l, h);
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ void PathFind::set_path_find(const char* navmesh_filename) {
|
|||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void PathFind::path_find(LVecBase3f pos, string type) {
|
||||
void PathFind::path_find(LVecBase3 pos, string type) {
|
||||
if(type == "addPath") {
|
||||
if(_ai_char->_steering->_path_follow_obj) {
|
||||
_ai_char->_steering->remove_ai("pathfollow");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
int _grid_size;
|
||||
NodePath _path_find_target;
|
||||
LVecBase3f _prev_position;
|
||||
LVecBase3 _prev_position;
|
||||
PT(GeomNode) _parent;
|
||||
LineSegs *_pen;
|
||||
vector<int> _previous_obstacles;
|
||||
|
|
@ -62,7 +62,7 @@ public:
|
|||
void clear_previous_obstacles();
|
||||
|
||||
void set_path_find(const char* navmesh_filename);
|
||||
void path_find(LVecBase3f pos, string type = "normal");
|
||||
void path_find(LVecBase3 pos, string type = "normal");
|
||||
void path_find(NodePath target, string type = "normal");
|
||||
void add_obstacle_to_mesh(NodePath obstacle);
|
||||
void dynamic_avoid(NodePath obstacle);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ PathFollow::~PathFollow() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PathFollow::add_to_path(LVecBase3f pos) {
|
||||
void PathFollow::add_to_path(LVecBase3 pos) {
|
||||
_path.push_back(pos);
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ void PathFollow::do_follow() {
|
|||
|
||||
bool PathFollow::check_if_possible() {
|
||||
Node* src = find_in_mesh(_ai_char->_steering->_path_find_obj->_nav_mesh, _ai_char->_ai_char_np.get_pos(_ai_char->_window_render), _ai_char->_steering->_path_find_obj->_grid_size);
|
||||
LVecBase3f _prev_position = _ai_char->_steering->_path_find_obj->_path_find_target.get_pos(_ai_char->_window_render);
|
||||
LVecBase3 _prev_position = _ai_char->_steering->_path_find_obj->_path_find_target.get_pos(_ai_char->_window_render);
|
||||
Node* dst = find_in_mesh(_ai_char->_steering->_path_find_obj->_nav_mesh, _prev_position, _ai_char->_steering->_path_find_obj->_grid_size);
|
||||
|
||||
if(src && dst) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class EXPCL_PANDAAI PathFollow {
|
|||
public:
|
||||
AICharacter *_ai_char;
|
||||
float _follow_weight;
|
||||
vector<LVecBase3f> _path;
|
||||
vector<LVecBase3> _path;
|
||||
int _curr_path_waypoint;
|
||||
bool _start;
|
||||
NodePath _dummy;
|
||||
|
|
@ -23,7 +23,7 @@ public:
|
|||
|
||||
PathFollow(AICharacter *ai_ch, float follow_wt);
|
||||
~PathFollow();
|
||||
void add_to_path(LVecBase3f pos);
|
||||
void add_to_path(LVecBase3 pos);
|
||||
void start(string type);
|
||||
void do_follow();
|
||||
bool check_if_possible();
|
||||
|
|
|
|||
|
|
@ -37,17 +37,17 @@ Pursue::~Pursue() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Pursue::do_pursue() {
|
||||
LVecBase3 Pursue::do_pursue() {
|
||||
assert(_pursue_target && "pursue target not assigned");
|
||||
|
||||
LVecBase3f present_pos = _ai_char->_ai_char_np.get_pos(_ai_char->_window_render);
|
||||
LVecBase3 present_pos = _ai_char->_ai_char_np.get_pos(_ai_char->_window_render);
|
||||
double target_distance = (_pursue_target.get_pos(_ai_char->_window_render) - present_pos).length();
|
||||
|
||||
if(int(target_distance) == 0) {
|
||||
_pursue_done = true;
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_pursue_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_pursue_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
_pursue_done = false;
|
||||
|
|
@ -56,6 +56,6 @@ LVecBase3f Pursue::do_pursue() {
|
|||
_pursue_direction = _pursue_target.get_pos(_ai_char->_window_render) - present_pos;
|
||||
_pursue_direction.normalize();
|
||||
|
||||
LVecBase3f desired_force = _pursue_direction * _ai_char->_movt_force;
|
||||
LVecBase3 desired_force = _pursue_direction * _ai_char->_movt_force;
|
||||
return(desired_force);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ public:
|
|||
|
||||
NodePath _pursue_target;
|
||||
float _pursue_weight;
|
||||
LVecBase3f _pursue_direction;
|
||||
LVecBase3 _pursue_direction;
|
||||
bool _pursue_done;
|
||||
|
||||
Pursue(AICharacter *ai_ch, NodePath target_object, float pursue_wt);
|
||||
~Pursue();
|
||||
LVecBase3f do_pursue();
|
||||
LVecBase3 do_pursue();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ Seek::Seek(AICharacter *ai_ch, NodePath target_object, float seek_wt) {
|
|||
_seek_done = false;
|
||||
}
|
||||
|
||||
Seek::Seek(AICharacter *ai_ch, LVecBase3f pos, float seek_wt) {
|
||||
Seek::Seek(AICharacter *ai_ch, LVecBase3 pos, float seek_wt) {
|
||||
_ai_char = ai_ch;
|
||||
|
||||
_seek_position = pos;
|
||||
|
|
@ -51,16 +51,16 @@ Seek::~Seek() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Seek::do_seek() {
|
||||
LVecBase3 Seek::do_seek() {
|
||||
double target_distance = (_seek_position - _ai_char->_ai_char_np.get_pos(_ai_char->_window_render)).length();
|
||||
|
||||
if(int(target_distance) == 0) {
|
||||
_seek_done = true;
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->turn_off("seek");
|
||||
return(LVecBase3f(0.0, 0.0, 0.0));
|
||||
return(LVecBase3(0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
LVecBase3f desired_force = _seek_direction * _ai_char->_movt_force;
|
||||
LVecBase3 desired_force = _seek_direction * _ai_char->_movt_force;
|
||||
return(desired_force);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,16 +26,16 @@ class EXPCL_PANDAAI Seek {
|
|||
public:
|
||||
AICharacter *_ai_char;
|
||||
|
||||
LVecBase3f _seek_position;
|
||||
LVecBase3 _seek_position;
|
||||
float _seek_weight;
|
||||
LVecBase3f _seek_direction;
|
||||
LVecBase3 _seek_direction;
|
||||
bool _seek_done;
|
||||
LVecBase3f _seek_accum_force;
|
||||
LVecBase3 _seek_accum_force;
|
||||
|
||||
Seek(AICharacter *ai_ch, NodePath target_object, float seek_wt = 1.0);
|
||||
Seek(AICharacter *ai_ch, LVecBase3f pos, float seek_wt = 1.0);
|
||||
Seek(AICharacter *ai_ch, LVecBase3 pos, float seek_wt = 1.0);
|
||||
~Seek();
|
||||
LVecBase3f do_seek();
|
||||
LVecBase3 do_seek();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,23 +57,23 @@ Wander::Wander(AICharacter *ai_ch, double wander_radius,int flag, double aoe, fl
|
|||
// default is XY axes
|
||||
switch(_flag) {
|
||||
case 0: {
|
||||
_wander_target = LVecBase3f(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
|
||||
_wander_target = LVecBase3(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
_wander_target = LVecBase3f(0, _wander_radius * cos(theta), _wander_radius * sin(theta));
|
||||
_wander_target = LVecBase3(0, _wander_radius * cos(theta), _wander_radius * sin(theta));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
_wander_target = LVecBase3f(_wander_radius * cos(theta), 0, _wander_radius * sin(theta));
|
||||
_wander_target = LVecBase3(_wander_radius * cos(theta), 0, _wander_radius * sin(theta));
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
_wander_target = LVecBase3f(_wander_radius * sin(theta) * cos(si), _wander_radius * sin(theta) * sin(si), _wander_radius * cos(theta));
|
||||
_wander_target = LVecBase3(_wander_radius * sin(theta) * cos(si), _wander_radius * sin(theta) * sin(si), _wander_radius * cos(theta));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
_wander_target = LVecBase3f(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
|
||||
_wander_target = LVecBase3(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -91,52 +91,52 @@ Wander::~Wander() {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LVecBase3f Wander::do_wander() {
|
||||
LVecBase3f present_pos = _ai_char->get_node_path().get_pos(_ai_char->get_char_render());
|
||||
LVecBase3 Wander::do_wander() {
|
||||
LVecBase3 present_pos = _ai_char->get_node_path().get_pos(_ai_char->get_char_render());
|
||||
// Create the random slices to enable random movement of wander for x,y,z respectively
|
||||
double time_slice_1 = random_clamped() * 1.5;
|
||||
double time_slice_2 = random_clamped() * 1.5;
|
||||
double time_slice_3 = random_clamped() * 1.5;
|
||||
switch(_flag) {
|
||||
case 0: {
|
||||
_wander_target += LVecBase3f(time_slice_1, time_slice_2, 0);
|
||||
_wander_target += LVecBase3(time_slice_1, time_slice_2, 0);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
_wander_target += LVecBase3f(0, time_slice_1, time_slice_2);
|
||||
_wander_target += LVecBase3(0, time_slice_1, time_slice_2);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
_wander_target += LVecBase3f(time_slice_1, 0, time_slice_2);
|
||||
_wander_target += LVecBase3(time_slice_1, 0, time_slice_2);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
_wander_target += LVecBase3f(time_slice_1, time_slice_2, time_slice_3);
|
||||
_wander_target += LVecBase3(time_slice_1, time_slice_2, time_slice_3);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
_wander_target = LVecBase3f(time_slice_1, time_slice_2, 0);
|
||||
_wander_target = LVecBase3(time_slice_1, time_slice_2, 0);
|
||||
}
|
||||
}
|
||||
_wander_target.normalize();
|
||||
_wander_target *= _wander_radius;
|
||||
LVecBase3f target = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3f::forward());
|
||||
LVecBase3 target = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
|
||||
target.normalize();
|
||||
// Project wander target onto global space
|
||||
target = _wander_target + target;
|
||||
LVecBase3f desired_target = present_pos + target;
|
||||
LVecBase3f desired_force = desired_target - _ai_char->get_node_path().get_pos() ;
|
||||
LVecBase3 desired_target = present_pos + target;
|
||||
LVecBase3 desired_force = desired_target - _ai_char->get_node_path().get_pos() ;
|
||||
desired_force.normalize();
|
||||
desired_force *= _ai_char->_movt_force;
|
||||
double distance = (present_pos - _init_pos).length();
|
||||
if(_area_of_effect > 0 && distance > _area_of_effect) {
|
||||
LVecBase3f direction = present_pos - _init_pos;
|
||||
LVecBase3 direction = present_pos - _init_pos;
|
||||
direction.normalize();
|
||||
desired_force = - direction * _ai_char->_movt_force;
|
||||
LVecBase3f dirn = _ai_char->_steering->_steering_force;
|
||||
LVecBase3 dirn = _ai_char->_steering->_steering_force;
|
||||
dirn.normalize();
|
||||
_ai_char->_steering->_steering_force = LVecBase3f(0.0, 0.0, 0.0);
|
||||
_ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
|
||||
}
|
||||
return desired_force;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ class EXPCL_PANDAAI Wander {
|
|||
public:
|
||||
AICharacter *_ai_char;
|
||||
double _wander_radius;
|
||||
LVecBase3f _wander_target;
|
||||
LVecBase3 _wander_target;
|
||||
float _wander_weight;
|
||||
int _flag;
|
||||
LVecBase3f _init_pos;
|
||||
LVecBase3 _init_pos;
|
||||
double _area_of_effect;
|
||||
|
||||
Wander(AICharacter *ai_ch, double wander_radius, int flag, double aoe, float wander_weight);
|
||||
LVecBase3f do_wander();
|
||||
LVecBase3 do_wander();
|
||||
~Wander();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -760,13 +760,13 @@ STRIP_CODE_COMMENTS = YES
|
|||
# then for each documented function all documented
|
||||
# functions referencing it will be listed.
|
||||
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
|
||||
# If the REFERENCES_RELATION tag is set to YES
|
||||
# then for each documented function all documented entities
|
||||
# called/used by that function will be listed.
|
||||
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_RELATION = NO
|
||||
|
||||
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
|
||||
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ def comment(code):
|
|||
if empty_line:
|
||||
# New paragraph.
|
||||
comment += '\n\n'
|
||||
empty_line = False
|
||||
elif comment:
|
||||
comment += '\n'
|
||||
comment += '/// ' + line
|
||||
|
|
@ -56,15 +57,29 @@ def block_comment(code):
|
|||
|
||||
line = line.rstrip()
|
||||
strline = line.lstrip('/ \t')
|
||||
if reading_desc:
|
||||
newlines.append('/// ' + line[min(indent, len(line) - len(strline)):])
|
||||
else:
|
||||
# A "Description:" text starts the description.
|
||||
if strline.startswith("Description"):
|
||||
strline = strline[11:].lstrip(': \t')
|
||||
indent = len(line) - len(strline)
|
||||
reading_desc = True
|
||||
newlines.append('/// ' + strline)
|
||||
|
||||
if ':' in strline:
|
||||
pre, post = strline.split(':', 1)
|
||||
pre = pre.rstrip()
|
||||
if pre == "Description":
|
||||
strline = post.lstrip()
|
||||
elif pre in ("Class", "Access", "Function", "Created by", "Enum"):
|
||||
continue
|
||||
|
||||
if strline or len(newlines) > 0:
|
||||
newlines.append('/// ' + strline)
|
||||
|
||||
#if reading_desc:
|
||||
# newlines.append('/// ' + line[min(indent, len(line) - len(strline)):])
|
||||
#else:
|
||||
# # A "Description:" text starts the description.
|
||||
# if strline.startswith("Description"):
|
||||
# strline = strline[11:].lstrip(': \t')
|
||||
# indent = len(line) - len(strline)
|
||||
# reading_desc = True
|
||||
# newlines.append('/// ' + strline)
|
||||
# else:
|
||||
# print line
|
||||
|
||||
newcode = '\n'.join(newlines)
|
||||
if len(newcode) > 0:
|
||||
|
|
@ -73,6 +88,9 @@ def block_comment(code):
|
|||
return ""
|
||||
|
||||
def translateFunctionName(name):
|
||||
if name.startswith("__"):
|
||||
return name
|
||||
|
||||
new = ""
|
||||
for i in name.split("_"):
|
||||
if new == "":
|
||||
|
|
@ -85,32 +103,58 @@ def translateFunctionName(name):
|
|||
new += i[0].upper() + i[1:]
|
||||
return new
|
||||
|
||||
def translated_type_name(type):
|
||||
def translateTypeName(name, mangle=True):
|
||||
# Equivalent to C++ classNameFromCppName
|
||||
class_name = ""
|
||||
bad_chars = "!@#$%^&*()<>,.-=+~{}? "
|
||||
next_cap = False
|
||||
first_char = mangle
|
||||
|
||||
for chr in name:
|
||||
if (chr == '_' or chr == ' ') and mangle:
|
||||
next_cap = True
|
||||
elif chr in bad_chars:
|
||||
if not mangle:
|
||||
class_name += '_'
|
||||
elif next_cap or first_char:
|
||||
class_name += chr.upper()
|
||||
next_cap = False
|
||||
first_char = False
|
||||
else:
|
||||
class_name += chr
|
||||
|
||||
return class_name
|
||||
|
||||
def translated_type_name(type, scoped=True):
|
||||
while interrogate_type_is_wrapped(type):
|
||||
if interrogate_type_is_const(type):
|
||||
return 'const ' + translated_type_name(interrogate_type_wrapped_type(type))
|
||||
else:
|
||||
type = interrogate_type_wrapped_type(type)
|
||||
|
||||
typename = interrogate_type_name(type)
|
||||
if typename in ("PyObject", "_object"):
|
||||
return "object"
|
||||
|
||||
if interrogate_type_is_atomic(type):
|
||||
token = interrogate_type_atomic_token(type)
|
||||
if token == 7:
|
||||
return 'str'
|
||||
else:
|
||||
return typename
|
||||
|
||||
typename = interrogate_type_name(type)
|
||||
typename = typename.replace("< ", "").replace(" >", "")
|
||||
return typename
|
||||
typename = translateTypeName(typename)
|
||||
|
||||
def translateTypeSpec(name):
|
||||
name = name.strip("* ")
|
||||
name = name.replace("BitMask< unsigned int, 32 >", "BitMask32")
|
||||
name = name.replace("atomic ", "")
|
||||
name = name.replace("< ", "").replace(" >", "")
|
||||
if name == '_object':
|
||||
name = 'object'
|
||||
elif name == '_typeobject':
|
||||
name = 'type'
|
||||
return name
|
||||
if scoped and interrogate_type_is_nested(type):
|
||||
return translated_type_name(interrogate_type_outer_class(type)) + '::' + typename
|
||||
else:
|
||||
return typename
|
||||
|
||||
def processElement(handle, element):
|
||||
if interrogate_element_has_comment(element):
|
||||
print >>handle, comment(interrogate_element_comment(element))
|
||||
|
||||
print >>handle, translateTypeSpec(translated_type_name(interrogate_element_type(element))),
|
||||
print >>handle, translated_type_name(interrogate_element_type(element)),
|
||||
print >>handle, interrogate_element_name(element) + ';'
|
||||
|
||||
def processFunction(handle, function, isConstructor = False):
|
||||
|
|
@ -120,11 +164,12 @@ def processFunction(handle, function, isConstructor = False):
|
|||
print >>handle, block_comment(interrogate_wrapper_comment(wrapper))
|
||||
|
||||
if not isConstructor:
|
||||
if not interrogate_wrapper_number_of_parameters(wrapper) > 0 or not interrogate_wrapper_parameter_is_this(wrapper, 0):
|
||||
print >>handle, "static",
|
||||
if interrogate_function_is_method(function):
|
||||
if not interrogate_wrapper_number_of_parameters(wrapper) > 0 or not interrogate_wrapper_parameter_is_this(wrapper, 0):
|
||||
print >>handle, "static",
|
||||
|
||||
if interrogate_wrapper_has_return_value(wrapper):
|
||||
print >>handle, translateTypeSpec(translated_type_name(interrogate_wrapper_return_type(wrapper))),
|
||||
print >>handle, translated_type_name(interrogate_wrapper_return_type(wrapper)),
|
||||
else:
|
||||
pass#print >>handle, "void",
|
||||
|
||||
|
|
@ -137,7 +182,7 @@ def processFunction(handle, function, isConstructor = False):
|
|||
if not interrogate_wrapper_parameter_is_this(wrapper, i_param):
|
||||
if not first:
|
||||
print >>handle, ",",
|
||||
print >>handle, translateTypeSpec(translated_type_name(interrogate_wrapper_parameter_type(wrapper, i_param))),
|
||||
print >>handle, translated_type_name(interrogate_wrapper_parameter_type(wrapper, i_param)),
|
||||
if interrogate_wrapper_parameter_has_name(wrapper, i_param):
|
||||
print >>handle, interrogate_wrapper_parameter_name(wrapper, i_param),
|
||||
first = False
|
||||
|
|
@ -145,7 +190,7 @@ def processFunction(handle, function, isConstructor = False):
|
|||
print >>handle, ");"
|
||||
|
||||
def processType(handle, type):
|
||||
typename = translated_type_name(type)
|
||||
typename = translated_type_name(type, scoped=False)
|
||||
derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ]
|
||||
|
||||
if interrogate_type_has_comment(type):
|
||||
|
|
@ -157,7 +202,7 @@ def processType(handle, type):
|
|||
docstring = comment(interrogate_type_enum_value_comment(type, i_value))
|
||||
if docstring:
|
||||
print >>handle, docstring
|
||||
print >>handle, translateFunctionName(interrogate_type_enum_value_name(type, i_value)), "=", interrogate_type_enum_value(type, i_value), ","
|
||||
print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
|
||||
else:
|
||||
if interrogate_type_is_struct(type):
|
||||
classtype = "struct"
|
||||
|
|
@ -192,38 +237,54 @@ def processType(handle, type):
|
|||
|
||||
print >>handle, "};"
|
||||
|
||||
def processModule(handle, package):
|
||||
print >>handle, "namespace %s {" % package
|
||||
|
||||
if package != "core":
|
||||
print >>handle, "using namespace core;"
|
||||
|
||||
for i_type in xrange(interrogate_number_of_global_types()):
|
||||
type = interrogate_get_global_type(i_type)
|
||||
|
||||
if interrogate_type_has_module_name(type):
|
||||
module_name = interrogate_type_module_name(type)
|
||||
if "panda3d." + package == module_name:
|
||||
processType(handle, type)
|
||||
else:
|
||||
print "Type %s has no module name" % typename
|
||||
|
||||
for i_func in xrange(interrogate_number_of_global_functions()):
|
||||
func = interrogate_get_global_function(i_func)
|
||||
|
||||
if interrogate_function_has_module_name(func):
|
||||
module_name = interrogate_function_module_name(func)
|
||||
if "panda3d." + package == module_name:
|
||||
processFunction(handle, func)
|
||||
else:
|
||||
print "Type %s has no module name" % typename
|
||||
|
||||
print >>handle, "}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
handle = open("pandadoc.hpp", "w")
|
||||
|
||||
print >>handle, comment("Panda3D modules that are implemented in C++.")
|
||||
print >>handle, "namespace panda3d {}"
|
||||
print >>handle, "namespace panda3d {"
|
||||
|
||||
# Determine the path to the interrogatedb files
|
||||
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "..", "..", "etc"))
|
||||
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "input"))
|
||||
|
||||
import panda3d.core
|
||||
processModule(handle, "core")
|
||||
|
||||
for lib in os.listdir(os.path.dirname(panda3d.__file__)):
|
||||
if lib.endswith(('.pyd', '.so')) and not lib.startswith('core.'):
|
||||
__import__('panda3d.' + os.path.splitext(lib)[0])
|
||||
module_name = os.path.splitext(lib)[0]
|
||||
__import__("panda3d." + module_name)
|
||||
processModule(handle, module_name)
|
||||
|
||||
lastpkg = None
|
||||
for i_type in xrange(interrogate_number_of_global_types()):
|
||||
type = interrogate_get_global_type(i_type)
|
||||
|
||||
if interrogate_type_has_module_name(type):
|
||||
package = interrogate_type_module_name(type)
|
||||
if lastpkg != package:
|
||||
if lastpkg is not None:
|
||||
print >>handle, "}"
|
||||
print >>handle, "namespace %s {" % package
|
||||
lastpkg = package
|
||||
|
||||
processType(handle, type)
|
||||
else:
|
||||
print "Type %s has no module name" % typename
|
||||
|
||||
if lastpkg is not None:
|
||||
print >>handle, "}"
|
||||
print >>handle, "}"
|
||||
handle.close()
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ class FilterManager(DirectObject):
|
|||
|
||||
winprops = WindowProperties()
|
||||
winprops.setSize(xsize, ysize)
|
||||
props = FrameBufferProperties(self.win.getFbProperties())
|
||||
props = FrameBufferProperties(FrameBufferProperties.getDefault())
|
||||
props.setBackBuffers(0)
|
||||
props.setRgbColor(1)
|
||||
props.setDepthBits(depthbits)
|
||||
|
|
|
|||
|
|
@ -94,8 +94,9 @@ class DirectDialog(DirectFrame):
|
|||
('text', '', None),
|
||||
('text_align', TextNode.ALeft, None),
|
||||
('text_scale', 0.06, None),
|
||||
('image', DGG.getDefaultDialogGeom(), None),
|
||||
('relief', None, None),
|
||||
('image', None, None),
|
||||
('relief', DGG.RAISED, None),
|
||||
('borderWidth', (0.01, 0.01), None),
|
||||
('buttonTextList', [], DGG.INITOPT),
|
||||
('buttonGeomList', [], DGG.INITOPT),
|
||||
('buttonImageList', [], DGG.INITOPT),
|
||||
|
|
@ -210,10 +211,16 @@ class DirectDialog(DirectFrame):
|
|||
bounds = self.stateNodePath[0].getTightBounds()
|
||||
if image:
|
||||
image.reparentTo(self.stateNodePath[0])
|
||||
l = bounds[0][0]
|
||||
r = bounds[1][0]
|
||||
b = bounds[0][2]
|
||||
t = bounds[1][2]
|
||||
if bounds is None:
|
||||
l = 0
|
||||
r = 0
|
||||
b = 0
|
||||
t = 0
|
||||
else:
|
||||
l = bounds[0][0]
|
||||
r = bounds[1][0]
|
||||
b = bounds[0][2]
|
||||
t = bounds[1][2]
|
||||
# Center text and geom around origin
|
||||
# How far is center of text from origin?
|
||||
xOffset = -(l+r)*0.5
|
||||
|
|
@ -246,10 +253,16 @@ class DirectDialog(DirectFrame):
|
|||
bl = br = bb = bt = 0
|
||||
for button in self.buttonList:
|
||||
bounds = button.stateNodePath[0].getTightBounds()
|
||||
bl = min(bl, bounds[0][0])
|
||||
br = max(br, bounds[1][0])
|
||||
bb = min(bb, bounds[0][2])
|
||||
bt = max(bt, bounds[1][2])
|
||||
if bounds is None:
|
||||
bl = 0
|
||||
br = 0
|
||||
bb = 0
|
||||
bt = 0
|
||||
else:
|
||||
bl = min(bl, bounds[0][0])
|
||||
br = max(br, bounds[1][0])
|
||||
bb = min(bb, bounds[0][2])
|
||||
bt = max(bt, bounds[1][2])
|
||||
bl -= bpad[0]
|
||||
br += bpad[0]
|
||||
bb -= bpad[1]
|
||||
|
|
@ -303,6 +316,7 @@ class DirectDialog(DirectFrame):
|
|||
# reduce bottom by pad, button height and 2*button pad
|
||||
b = min(b - self['midPad'] - bpad[1] - bHeight - bpad[1], b) - pad[1]
|
||||
t = t + self['topPad'] + pad[1]
|
||||
self['frameSize'] = (l, r, b, t)
|
||||
self['image_scale'] = (r - l, 1, t - b)
|
||||
# Center frame about text and buttons
|
||||
self['image_pos'] = ((l+r)*0.5, 0.0, (b+t)*0.5)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class DirectRadioButton(DirectButton):
|
|||
('boxGeom', None, None),
|
||||
('boxGeomColor', None, None),
|
||||
('boxGeomScale', 1.0, None),
|
||||
('boxImage', loader.loadModel('models/gui/radio_button_gui'), None),
|
||||
('boxImage', None, None),
|
||||
('boxImageScale', 1.0, None),
|
||||
('boxImageColor', VBase4(1, 1, 1, 1), None),
|
||||
('boxRelief', None, None),
|
||||
|
|
@ -69,9 +69,11 @@ class DirectRadioButton(DirectButton):
|
|||
# Call option initialization functions
|
||||
self.initialiseoptions(DirectRadioButton)
|
||||
# After initialization with X giving it the correct size, put back space
|
||||
if self['boxGeom'] == None:
|
||||
if self['boxGeom'] is None:
|
||||
if not 'boxRelief' in kw and self['boxImage'] is None:
|
||||
self.indicator['relief'] = DGG.SUNKEN
|
||||
self.indicator['text'] = (' ', '*')
|
||||
self.indicator['text_pos'] = (0, -.5)
|
||||
self.indicator['text_pos'] = (0, -.25)
|
||||
else:
|
||||
self.indicator['text'] = (' ', ' ')
|
||||
|
||||
|
|
|
|||
|
|
@ -59,15 +59,12 @@ class Transitions:
|
|||
|
||||
# Reload fade if its already been created
|
||||
if self.fade:
|
||||
del self.fade
|
||||
self.fade.destroy()
|
||||
self.fade = None
|
||||
self.loadFade()
|
||||
|
||||
def loadFade(self):
|
||||
if not self.fadeModel:
|
||||
self.fadeModel = loader.loadModel(self.FadeModelName)
|
||||
|
||||
if self.fade == None:
|
||||
if self.fade is None:
|
||||
# We create a DirectFrame for the fade polygon, instead of
|
||||
# simply loading the polygon model and using it directly,
|
||||
# so that it will also obscure mouse events for objects
|
||||
|
|
@ -80,10 +77,15 @@ class Transitions:
|
|||
image_scale = (4, 2, 2),
|
||||
state = DGG.NORMAL,
|
||||
)
|
||||
if not self.fadeModel:
|
||||
# No fade model was given, so we make this the fade model.
|
||||
self.fade["relief"] = DGG.FLAT
|
||||
self.fade["frameSize"] = (-2, 2, -1, 1)
|
||||
self.fade["frameColor"] = (0, 0, 0, 1)
|
||||
self.fade.setTransparency(TransparencyAttrib.MAlpha)
|
||||
self.fade.setBin('unsorted', 0)
|
||||
self.fade.setColor(0,0,0,0)
|
||||
|
||||
|
||||
def getFadeInIval(self, t=0.5, finishIval=None):
|
||||
"""
|
||||
Returns an interval without starting it. This is particularly useful in
|
||||
|
|
|
|||
|
|
@ -4625,8 +4625,14 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||
format_specifiers += "h";
|
||||
parameter_list += ", &" + param_name;
|
||||
}
|
||||
expected_params += "int";
|
||||
only_pyobjects = false;
|
||||
|
||||
extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
|
||||
extra_param_check += " && " + param_name + "_long != NULL";
|
||||
pexpr_string = "(" + type->get_local_name(&parser) + ")" +
|
||||
"PyLong_AsLongLong(" + param_name + "_long)";
|
||||
extra_cleanup += "Py_XDECREF(" + param_name + "_long);";
|
||||
expected_params += "long long";
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_unsigned_integer(type)) {
|
||||
if (args_type == AT_single_arg) {
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@ def CompileCxx(obj,src,opts):
|
|||
if PkgSkip("TOUCHINPUT") == 0:
|
||||
cmd += "/DWINVER=0x601 "
|
||||
cmd += "/Fo" + obj + " /nologo /c"
|
||||
if (GetTargetArch() != 'x64' and PkgSkip("SSE2") == 0):
|
||||
if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts):
|
||||
cmd += " /arch:SSE2"
|
||||
for x in ipath: cmd += " /I" + x
|
||||
for (opt,dir) in INCDIRECTORIES:
|
||||
|
|
@ -1160,7 +1160,7 @@ def CompileCxx(obj,src,opts):
|
|||
if optlevel >= 4 or GetTarget() == "android":
|
||||
cmd += " -fno-rtti"
|
||||
|
||||
if PkgSkip("SSE2") == 0 and not arch.startswith("arm"):
|
||||
if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm"):
|
||||
cmd += " -msse2"
|
||||
|
||||
if optlevel >= 3:
|
||||
|
|
@ -1705,7 +1705,7 @@ def RunGenPyCode(target, inputs, opts):
|
|||
if (PkgSkip("PYTHON") != 0):
|
||||
return
|
||||
|
||||
cmdstr = sys.executable + " "
|
||||
cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
|
||||
if sys.version_info >= (2, 6):
|
||||
cmdstr += "-B "
|
||||
|
||||
|
|
@ -1729,7 +1729,7 @@ def RunGenPyCode(target, inputs, opts):
|
|||
def FreezePy(target, inputs, opts):
|
||||
assert len(inputs) > 0
|
||||
# Make sure this function isn't called before genpycode is run.
|
||||
cmdstr = sys.executable + " "
|
||||
cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
|
||||
if sys.version_info >= (2, 6):
|
||||
cmdstr += "-B "
|
||||
|
||||
|
|
@ -1757,7 +1757,7 @@ def FreezePy(target, inputs, opts):
|
|||
def Package(target, inputs, opts):
|
||||
assert len(inputs) == 1
|
||||
# Invoke the ppackage script.
|
||||
command = sys.executable + " "
|
||||
command = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
|
||||
if GetOptimizeOption(opts) >= 4:
|
||||
command += "-OO "
|
||||
|
||||
|
|
@ -3192,6 +3192,7 @@ if (not RUNTIME):
|
|||
OPTS=['DIR:panda/src/pnmimage', 'BUILDING:PANDA', 'ZLIB']
|
||||
TargetAdd('p3pnmimage_composite1.obj', opts=OPTS, input='p3pnmimage_composite1.cxx')
|
||||
TargetAdd('p3pnmimage_composite2.obj', opts=OPTS, input='p3pnmimage_composite2.cxx')
|
||||
TargetAdd('p3pnmimage_convert_srgb_sse2.obj', opts=OPTS+['SSE2'], input='convert_srgb_sse2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/pnmimage', 'ZLIB']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/pnmimage', ["*.h", "*_composite*.cxx"])
|
||||
|
|
@ -3621,6 +3622,7 @@ if (not RUNTIME):
|
|||
TargetAdd('libpanda.dll', input='p3pnmimagetypes_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3pnmimage_composite1.obj')
|
||||
TargetAdd('libpanda.dll', input='p3pnmimage_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3pnmimage_convert_srgb_sse2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3text_composite1.obj')
|
||||
TargetAdd('libpanda.dll', input='p3text_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3tform_composite1.obj')
|
||||
|
|
|
|||
|
|
@ -1018,7 +1018,7 @@ make_tet_mesh(BulletSoftBodyWorldInfo &info, const char *ele, const char *face,
|
|||
|
||||
for (int i=0; i<pos.size(); ++i) {
|
||||
int index = 0;
|
||||
PN_stdfloat x, y, z;
|
||||
float x, y, z;
|
||||
|
||||
sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
|
||||
node += next_line(node);
|
||||
|
|
|
|||
|
|
@ -324,34 +324,31 @@ make_output(const string &name,
|
|||
}
|
||||
|
||||
// Second thing to try: a GLGraphicsBuffer
|
||||
|
||||
if (retry == 1) {
|
||||
if ((host==0)||
|
||||
// (!gl_support_fbo)||
|
||||
((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
if (!gl_support_fbo || host == NULL ||
|
||||
(flags & (BF_require_parasite | BF_require_window)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Early failure - if we are sure that this buffer WONT
|
||||
// meet specs, we can bail out early.
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
if ((fb_prop.get_indexed_color() > 0)||
|
||||
(fb_prop.get_back_buffers() > 0)||
|
||||
(fb_prop.get_accum_bits() > 0)||
|
||||
(fb_prop.get_multisamples() > 0)) {
|
||||
if ((flags & BF_fb_props_optional) == 0) {
|
||||
if (fb_prop.get_indexed_color() ||
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
if ((cocoagsg != 0) &&
|
||||
(cocoagsg->is_valid()) &&
|
||||
(!cocoagsg->needs_reset()) &&
|
||||
(cocoagsg->_supports_framebuffer_object) &&
|
||||
(cocoagsg->_glDrawBuffers != 0) &&
|
||||
(fb_prop.is_basic())) {
|
||||
precertify = true;
|
||||
if (cocoagsg != NULL && cocoagsg->is_valid() && !cocoagsg->needs_reset()) {
|
||||
if (!cocoagsg->_supports_framebuffer_object ||
|
||||
cocoagsg->_glDrawBuffers == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
|
||||
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,19 +418,13 @@ ConfigVariableInt depth_bits
|
|||
("depth-bits", 0,
|
||||
PRC_DESC("The minimum number of depth buffer bits requested."));
|
||||
ConfigVariableInt color_bits
|
||||
("color-bits", 0,
|
||||
PRC_DESC("The minimum number of total color buffer bits requested. This "
|
||||
"value is like red-bits + blue-bits + green-bits except Panda "
|
||||
"won't care how the bits are divided up."));
|
||||
ConfigVariableInt red_bits
|
||||
("red-bits", 0,
|
||||
PRC_DESC("The minimum number of red color buffer bits requested."));
|
||||
ConfigVariableInt green_bits
|
||||
("green-bits", 0,
|
||||
PRC_DESC("The minimum number of green color buffer bits requested."));
|
||||
ConfigVariableInt blue_bits
|
||||
("blue-bits", 0,
|
||||
PRC_DESC("The minimum number of blue color buffer bits requested."));
|
||||
("color-bits", "",
|
||||
PRC_DESC("The minimum number of total color buffer bits requested. If you "
|
||||
"specify only one value, it will represent the total value for the "
|
||||
"red, green and blue channels, and indicates you don't care how the "
|
||||
"bits are divided up among the red, green and blue channels. If "
|
||||
"you specify three values, it represents three separate red, green "
|
||||
"and blue bit requirements."));
|
||||
ConfigVariableInt alpha_bits
|
||||
("alpha-bits", 0,
|
||||
PRC_DESC("The minimum number of alpha buffer bits requested."));
|
||||
|
|
|
|||
|
|
@ -97,9 +97,6 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_srgb;
|
|||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_float;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt depth_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt color_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt red_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt green_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt blue_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt alpha_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt stencil_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt accum_bits;
|
||||
|
|
|
|||
|
|
@ -305,37 +305,42 @@ get_float_depth() const {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_depth_bits(int n) {
|
||||
_property[FBP_depth_bits] = n;
|
||||
_specified[FBP_depth_bits] = true;
|
||||
_specified |= (1 << FBP_depth_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FrameBufferProperties::set_color_bits
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description: Sets the number of requested color bits as a single
|
||||
// number that represents the sum of the individual
|
||||
// numbers of red, green and blue bits. Panda won't
|
||||
// care how the individual bits are divided up.
|
||||
//
|
||||
// See also set_rgba_bits, which allows you to specify
|
||||
// requirements for the individual components.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FrameBufferProperties::
|
||||
set_color_bits(int n) {
|
||||
_property[FBP_color_bits] = n;
|
||||
_specified[FBP_color_bits] = true;
|
||||
_specified |= (1 << FBP_color_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FrameBufferProperties::set_rgba_bits
|
||||
// Access: Published
|
||||
// Description: Sets all color bit requirements separately.
|
||||
// Description: Convenience method for setting the red, green, blue
|
||||
// and alpha bits in one go.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FrameBufferProperties::
|
||||
set_rgba_bits(int r, int g, int b, int a) {
|
||||
_property[FBP_red_bits] = r;
|
||||
_specified[FBP_red_bits] = true;
|
||||
_property[FBP_green_bits] = g;
|
||||
_specified[FBP_green_bits] = true;
|
||||
_property[FBP_blue_bits] = b;
|
||||
_specified[FBP_blue_bits] = true;
|
||||
_property[FBP_alpha_bits] = a;
|
||||
_specified[FBP_alpha_bits] = true;
|
||||
_property[FBP_color_bits] = r + g + b;
|
||||
_specified[FBP_color_bits] = true;
|
||||
_specified |= (1 << FBP_color_bits) | (1 << FBP_red_bits) |
|
||||
(1 << FBP_green_bits) | (1 << FBP_blue_bits) |
|
||||
(1 << FBP_alpha_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -346,7 +351,7 @@ set_rgba_bits(int r, int g, int b, int a) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_red_bits(int n) {
|
||||
_property[FBP_red_bits] = n;
|
||||
_specified[FBP_red_bits] = true;
|
||||
_specified |= (1 << FBP_red_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -357,7 +362,7 @@ set_red_bits(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_green_bits(int n) {
|
||||
_property[FBP_green_bits] = n;
|
||||
_specified[FBP_green_bits] = true;
|
||||
_specified |= (1 << FBP_green_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -368,7 +373,7 @@ set_green_bits(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_blue_bits(int n) {
|
||||
_property[FBP_blue_bits] = n;
|
||||
_specified[FBP_blue_bits] = true;
|
||||
_specified |= (1 << FBP_blue_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -379,7 +384,7 @@ set_blue_bits(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_alpha_bits(int n) {
|
||||
_property[FBP_alpha_bits] = n;
|
||||
_specified[FBP_alpha_bits] = true;
|
||||
_specified |= (1 << FBP_alpha_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -390,7 +395,7 @@ set_alpha_bits(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_stencil_bits(int n) {
|
||||
_property[FBP_stencil_bits] = n;
|
||||
_specified[FBP_stencil_bits] = true;
|
||||
_specified |= (1 << FBP_stencil_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -401,7 +406,7 @@ set_stencil_bits(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_accum_bits(int n) {
|
||||
_property[FBP_accum_bits] = n;
|
||||
_specified[FBP_accum_bits] = true;
|
||||
_specified |= (1 << FBP_accum_bits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -413,7 +418,7 @@ INLINE void FrameBufferProperties::
|
|||
set_aux_rgba(int n) {
|
||||
nassertv(n < 4);
|
||||
_property[FBP_aux_rgba] = n;
|
||||
_specified[FBP_aux_rgba] = true;
|
||||
_specified |= (1 << FBP_aux_rgba);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -425,7 +430,7 @@ INLINE void FrameBufferProperties::
|
|||
set_aux_hrgba(int n) {
|
||||
nassertv(n < 4);
|
||||
_property[FBP_aux_hrgba] = n;
|
||||
_specified[FBP_aux_hrgba] = true;
|
||||
_specified |= (1 << FBP_aux_hrgba);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -437,7 +442,7 @@ INLINE void FrameBufferProperties::
|
|||
set_aux_float(int n) {
|
||||
nassertv(n < 4);
|
||||
_property[FBP_aux_float] = n;
|
||||
_specified[FBP_aux_float] = true;
|
||||
_specified |= (1 << FBP_aux_float);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -448,7 +453,7 @@ set_aux_float(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_multisamples(int n) {
|
||||
_property[FBP_multisamples] = n;
|
||||
_specified[FBP_multisamples] = true;
|
||||
_specified |= (1 << FBP_multisamples);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -460,7 +465,7 @@ set_multisamples(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_coverage_samples(int n) {
|
||||
_property[FBP_coverage_samples] = n;
|
||||
_specified[FBP_coverage_samples] = true;
|
||||
_specified |= (1 << FBP_coverage_samples);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -471,7 +476,7 @@ set_coverage_samples(int n) {
|
|||
INLINE void FrameBufferProperties::
|
||||
set_back_buffers(int n) {
|
||||
_property[FBP_back_buffers] = n;
|
||||
_specified[FBP_back_buffers] = true;
|
||||
_specified |= (1 << FBP_back_buffers);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ void FrameBufferProperties::
|
|||
operator = (const FrameBufferProperties ©) {
|
||||
_flags_specified = copy._flags_specified;
|
||||
_flags = copy._flags;
|
||||
_specified = copy._specified;
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
_specified[i] = copy._specified[i];
|
||||
_property[i] = copy._property[i];
|
||||
}
|
||||
}
|
||||
|
|
@ -144,17 +144,24 @@ get_default() {
|
|||
if (depth_bits > 0) {
|
||||
default_props.set_depth_bits(depth_bits);
|
||||
}
|
||||
if (color_bits > 0) {
|
||||
default_props.set_color_bits(color_bits);
|
||||
}
|
||||
if (red_bits > 0) {
|
||||
default_props.set_red_bits(red_bits);
|
||||
}
|
||||
if (green_bits > 0) {
|
||||
default_props.set_green_bits(green_bits);
|
||||
}
|
||||
if (blue_bits > 0) {
|
||||
default_props.set_blue_bits(blue_bits);
|
||||
switch (color_bits.size()) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
default_props.set_color_bits(color_bits[0]);
|
||||
break;
|
||||
case 3:
|
||||
default_props.set_color_bits(color_bits[0] + color_bits[1] + color_bits[2]);
|
||||
default_props.set_red_bits(color_bits[0]);
|
||||
default_props.set_green_bits(color_bits[1]);
|
||||
default_props.set_blue_bits(color_bits[2]);
|
||||
break;
|
||||
default:
|
||||
default_props.set_color_bits(color_bits[0]);
|
||||
display_cat.error()
|
||||
<< "Configuration variable color-bits takes either 1 or 3 values, not "
|
||||
<< color_bits.size() << "\n";
|
||||
break;
|
||||
}
|
||||
if (alpha_bits > 0) {
|
||||
default_props.set_alpha_bits(alpha_bits);
|
||||
|
|
@ -189,10 +196,11 @@ operator == (const FrameBufferProperties &other) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (_specified != other._specified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
if (_specified[i] != other._specified[i]) {
|
||||
return false;
|
||||
}
|
||||
if (_property[i] != other._property[i]) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -214,9 +222,9 @@ clear() {
|
|||
_flags_specified = 0;
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
_specified[i] = 0;
|
||||
_property[i] = 0;
|
||||
}
|
||||
_specified = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -232,9 +240,9 @@ add_properties(const FrameBufferProperties &other) {
|
|||
_flags |= other._flags & other._flags_specified;
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
if (other._specified[i]) {
|
||||
if (other._specified & (1 << i)) {
|
||||
_property[i] = other._property[i];
|
||||
_specified[i] = true;
|
||||
_specified |= (1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -364,30 +372,18 @@ get_buffer_mask() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool FrameBufferProperties::
|
||||
is_any_specified() const {
|
||||
if (_flags_specified != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
if (_specified[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return (_flags_specified | _specified) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FrameBufferProperties::set_all_specified
|
||||
// Access: Published
|
||||
// Description: sets all the specified bits.
|
||||
// Description: Marks all bits as having been specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FrameBufferProperties::
|
||||
set_all_specified() {
|
||||
_flags_specified = FBF_all;
|
||||
|
||||
for (int i = 0; i < FBP_COUNT; ++i) {
|
||||
_specified[i] = true;
|
||||
}
|
||||
_specified = (1 << FBP_COUNT) - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ private:
|
|||
};
|
||||
|
||||
int _property[FBP_COUNT];
|
||||
bool _specified[FBP_COUNT];
|
||||
int _specified;
|
||||
|
||||
int _flags;
|
||||
int _flags_specified;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NonlinearImager::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NonlinearImager::
|
||||
NonlinearImager() {
|
||||
|
|
@ -38,7 +38,7 @@ NonlinearImager() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NonlinearImager::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NonlinearImager::
|
||||
~NonlinearImager() {
|
||||
|
|
@ -54,7 +54,7 @@ NonlinearImager::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NonlinearImager::add_screen
|
||||
// Access: Published
|
||||
// This version of this method is deprecated and will
|
||||
// Description: This version of this method is deprecated and will
|
||||
// soon be removed. Use the version that takes two
|
||||
// parameters instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1476,6 +1476,10 @@ GROUPING ENTRIES
|
|||
its geometry is used to define the extent of the collision
|
||||
surface (unless the "descend" flag is given; see below).
|
||||
|
||||
It is now deprecated to use <Collide> without "descend"; it will
|
||||
become the default soon. You should always specify it for best
|
||||
compatibility.
|
||||
|
||||
Valid types so far are:
|
||||
|
||||
Plane
|
||||
|
|
@ -1538,11 +1542,12 @@ GROUPING ENTRIES
|
|||
|
||||
descend
|
||||
|
||||
Instead of creating only one collision object of the given type,
|
||||
each group descended from this node that contains geometry will
|
||||
Each group descended from this node that contains geometry will
|
||||
define a new collision object of the given type. The event
|
||||
name, if any, will also be inherited from the top node and
|
||||
shared among all the collision objects.
|
||||
shared among all the collision objects. This option will soon
|
||||
be the default; it is suggested that it is always specified for
|
||||
most compatibility.
|
||||
|
||||
keep
|
||||
|
||||
|
|
|
|||
|
|
@ -2970,6 +2970,10 @@ make_collision_solids(EggGroup *start_group, EggGroup *egg_group,
|
|||
make_collision_solids(start_group, DCAST(EggGroup, *ci), cnode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
egg2pg_cat.warning()
|
||||
<< "Using <Collide> without 'descend' is deprecated. 'descend' "
|
||||
<< "will become the default in a future version of Panda3D.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ CLP(CgShaderContext)::
|
|||
CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) {
|
||||
_glgsg = glgsg;
|
||||
_cg_program = 0;
|
||||
_glsl_profile = false;
|
||||
|
||||
nassertv(s->get_language() == Shader::SL_Cg);
|
||||
|
||||
|
|
@ -63,10 +62,6 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
release_resources();
|
||||
|
||||
} else {
|
||||
if (cgGetProgramProfile(_cg_program) == CG_PROFILE_GLSLC) {
|
||||
_glsl_profile = true;
|
||||
}
|
||||
|
||||
cgGLLoadProgram(_cg_program);
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
|
|
@ -351,14 +346,7 @@ issue_parameters(int altered) {
|
|||
if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) {
|
||||
const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered);
|
||||
if (!val) continue;
|
||||
#ifndef STDFLOAT_DOUBLE
|
||||
// In this case, the data is already single-precision.
|
||||
const PN_float32 *data = val->get_data();
|
||||
#else
|
||||
// In this case, we have to convert it.
|
||||
LMatrix4f valf = LCAST(PN_float32, *val);
|
||||
const PN_float32 *data = valf.get_data();
|
||||
#endif
|
||||
const PN_stdfloat *data = val->get_data();
|
||||
|
||||
CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno];
|
||||
switch (_shader->_mat_spec[i]._piece) {
|
||||
|
|
@ -377,13 +365,13 @@ issue_parameters(int altered) {
|
|||
case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue;
|
||||
case Shader::SMP_upper3x3:
|
||||
{
|
||||
LMatrix3f upper3 = val->get_upper_3();
|
||||
LMatrix3 upper3 = val->get_upper_3();
|
||||
GLfc(cgGLSetMatrixParameter)(p, upper3.get_data());
|
||||
continue;
|
||||
}
|
||||
case Shader::SMP_transpose3x3:
|
||||
{
|
||||
LMatrix3f upper3 = val->get_upper_3();
|
||||
LMatrix3 upper3 = val->get_upper_3();
|
||||
GLfr(cgGLSetMatrixParameter)(p, upper3.get_data());
|
||||
continue;
|
||||
}
|
||||
|
|
@ -412,7 +400,7 @@ disable_shader_vertex_arrays() {
|
|||
CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
|
||||
if (p == 0) continue;
|
||||
|
||||
if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
|
||||
if (cgGetParameterBaseResource(p) == CG_ATTR0) {
|
||||
int index = cgGetParameterResourceIndex(p);
|
||||
if (index >= 8) {
|
||||
_glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8));
|
||||
|
|
@ -501,11 +489,9 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
|||
num_values = GL_BGRA;
|
||||
}
|
||||
|
||||
// This is truly the most preposterous hack. When using the GLSL
|
||||
// profiles, cgGLSetParameterPointer relies on the the driver mapping
|
||||
// standard attributes to fixed indices (and breaking the spec doing
|
||||
// so), which only the NVIDIA drivers do. Unbelievable.
|
||||
if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
|
||||
// cgGLSetParameterPointer is just stupidly bugged on every level.
|
||||
// Sigh. This seems to work on both NVIDIA and AMD cards now.
|
||||
if (cgGetParameterBaseResource(p) == CG_ATTR0) {
|
||||
int index = cgGetParameterResourceIndex(p);
|
||||
switch (index) {
|
||||
case 0: // gl_Vertex
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ public:
|
|||
|
||||
private:
|
||||
CGprogram _cg_program;
|
||||
bool _glsl_profile;
|
||||
|
||||
pvector<CGparameter> _cg_parameter_map;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host),
|
||||
_bind_texture_pcollector(_draw_window_pcollector, "Bind textures"),
|
||||
_generate_mipmap_pcollector(_draw_window_pcollector, "Generate mipmaps"),
|
||||
_resolve_multisample_pcollector(_draw_window_pcollector, "Resolve multisamples")
|
||||
_resolve_multisample_pcollector(_draw_window_pcollector, "Resolve multisamples"),
|
||||
_requested_multisamples(0),
|
||||
_requested_coverage_samples(0)
|
||||
{
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
|
||||
// A FBO doesn't have a back buffer.
|
||||
_draw_buffer_type = RenderBuffer::T_front;
|
||||
_screenshot_buffer_type = RenderBuffer::T_front;
|
||||
|
|
@ -42,36 +42,6 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
_fbo_multisample = 0;
|
||||
_initial_clear = true;
|
||||
_needs_rebuild = true;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
|
||||
if (glgsg->get_supports_framebuffer_multisample() && glgsg->get_supports_framebuffer_blit()) {
|
||||
_requested_multisamples = fb_prop.get_multisamples();
|
||||
} else {
|
||||
_requested_multisamples = 0;
|
||||
}
|
||||
|
||||
if (glgsg->get_supports_framebuffer_multisample_coverage_nv() && glgsg->get_supports_framebuffer_blit()) {
|
||||
_requested_coverage_samples = fb_prop.get_coverage_samples();
|
||||
// Note: Only 4 and 8 actual samples are supported by the extension, with 8 or 16 coverage samples.
|
||||
if ((_requested_coverage_samples <= 8) && (_requested_coverage_samples > 0)) {
|
||||
_requested_multisamples = 4;
|
||||
_requested_coverage_samples = 8;
|
||||
} else if (_requested_coverage_samples > 8) {
|
||||
if (_requested_multisamples < 8) {
|
||||
_requested_multisamples = 4;
|
||||
} else {
|
||||
_requested_multisamples = 8;
|
||||
}
|
||||
_requested_coverage_samples = 16;
|
||||
}
|
||||
|
||||
} else {
|
||||
_requested_coverage_samples = 0;
|
||||
}
|
||||
|
||||
if (_requested_multisamples > glgsg->_max_fb_samples) {
|
||||
_requested_multisamples = glgsg->_max_fb_samples;
|
||||
}
|
||||
|
||||
_rb_size_x = 0;
|
||||
_rb_size_y = 0;
|
||||
|
|
@ -382,9 +352,9 @@ rebuild_bitplanes() {
|
|||
}
|
||||
}
|
||||
|
||||
// Decide whether we should use a depth stencil or just a regular depth attachment.
|
||||
// If nothing was attached to either RTP_depth_stencil or RTP_depth, we use a
|
||||
// depth-stencil renderbuffer.
|
||||
// Decide whether we should use a depth stencil or just a regular depth
|
||||
// attachment. If nothing was attached to either RTP_depth_stencil or
|
||||
// RTP_depth, we use a depth-stencil renderbuffer.
|
||||
_use_depth_stencil = false;
|
||||
if (_gsg->get_supports_depth_stencil()) {
|
||||
if (attach[RTP_depth_stencil]) {
|
||||
|
|
@ -396,19 +366,16 @@ rebuild_bitplanes() {
|
|||
// explicitly bound something to RTP_depth.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_float_depth()) {
|
||||
// Let's not bother with a depth-stencil buffer
|
||||
// if a float buffer was requested.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_depth_bits() > 24) {
|
||||
// We can't give more than 24 depth bits with a depth-stencil buffer.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_stencil_bits() > 0) {
|
||||
// The user requested stencil bits. Let's take the hint.
|
||||
_use_depth_stencil = true;
|
||||
|
||||
} else if (_fb_properties.get_depth_bits() > 24 ||
|
||||
_fb_properties.get_float_depth()) {
|
||||
// 32-bit float depth is supported in conjunction with depth stencil,
|
||||
// but it's a waste. Let's not do it unless the user requested stencil.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_depth_bits() > 0) {
|
||||
// Let's use a depth stencil buffer by default, if a depth
|
||||
// buffer was requested.
|
||||
|
|
@ -416,10 +383,9 @@ rebuild_bitplanes() {
|
|||
}
|
||||
}
|
||||
|
||||
// Knowing this, we can already be a tiny bit
|
||||
// more accurate about the framebuffer properties.
|
||||
// Knowing this, we can already be a tiny bit more accurate about the
|
||||
// framebuffer properties.
|
||||
if (_use_depth_stencil) {
|
||||
_fb_properties.set_depth_bits(24);
|
||||
_fb_properties.set_stencil_bits(8);
|
||||
} else {
|
||||
_fb_properties.set_stencil_bits(0);
|
||||
|
|
@ -553,8 +519,7 @@ rebuild_bitplanes() {
|
|||
#endif // OPENGLES
|
||||
|
||||
if (!_have_any_color) {
|
||||
_fb_properties.set_color_bits(0);
|
||||
_fb_properties.set_alpha_bits(0);
|
||||
_fb_properties.set_rgba_bits(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
_initial_clear = false;
|
||||
|
|
@ -699,8 +664,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
|
||||
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
|
||||
|
||||
_fb_properties.set_color_bits(red_size + green_size + blue_size);
|
||||
_fb_properties.set_alpha_bits(alpha_size);
|
||||
_fb_properties.set_rgba_bits(red_size, green_size, blue_size, alpha_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -717,6 +681,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
// No texture to bind. Instead, create a renderbuffer.
|
||||
// Choose a suitable renderbuffer format based on the requirements.
|
||||
#ifdef OPENGLES
|
||||
// OpenGL ES case.
|
||||
GLuint gl_format = GL_RGBA4;
|
||||
switch (slot) {
|
||||
case RTP_depth_stencil:
|
||||
|
|
@ -731,6 +696,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
gl_format = GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
break;
|
||||
//NB: we currently use RTP_stencil to store the right eye for stereo.
|
||||
//case RTP_stencil:
|
||||
// gl_format = GL_STENCIL_INDEX8;
|
||||
// break
|
||||
|
|
@ -762,7 +728,8 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
GLuint gl_format = GL_RGBA;
|
||||
switch (slot) {
|
||||
case RTP_depth_stencil:
|
||||
if (_fb_properties.get_float_depth()) {
|
||||
if (_fb_properties.get_depth_bits() > 24 ||
|
||||
_fb_properties.get_float_depth()) {
|
||||
gl_format = GL_DEPTH32F_STENCIL8;
|
||||
} else {
|
||||
gl_format = GL_DEPTH24_STENCIL8;
|
||||
|
|
@ -775,7 +742,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
gl_format = GL_DEPTH_COMPONENT32;
|
||||
} else if (_fb_properties.get_depth_bits() > 16) {
|
||||
gl_format = GL_DEPTH_COMPONENT24;
|
||||
} else if (_fb_properties.get_depth_bits() > 8) {
|
||||
} else if (_fb_properties.get_depth_bits() > 1) {
|
||||
gl_format = GL_DEPTH_COMPONENT16;
|
||||
} else {
|
||||
gl_format = GL_DEPTH_COMPONENT;
|
||||
|
|
@ -903,8 +870,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT, &green_size);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT, &blue_size);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT, &alpha_size);
|
||||
_fb_properties.set_color_bits(red_size + green_size + blue_size);
|
||||
_fb_properties.set_alpha_bits(alpha_size);
|
||||
_fb_properties.set_rgba_bits(red_size, green_size, blue_size, alpha_size);
|
||||
}
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
|
|
@ -976,7 +942,6 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
format = GL_DEPTH_COMPONENT32;
|
||||
break;
|
||||
default:
|
||||
format = GL_DEPTH_COMPONENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1269,14 +1234,12 @@ open_buffer() {
|
|||
|
||||
// Describe the framebuffer properties of the FBO.
|
||||
//
|
||||
// Unfortunately, we can't possibly predict which formats
|
||||
// Unfortunately, we can't currently predict which formats
|
||||
// the implementation will allow us to use at this point, so
|
||||
// we'll just have to make some guesses and parrot the rest
|
||||
// of the properties back to the user.
|
||||
// When we actually attach the textures, we'll update the
|
||||
// properties more appropriately.
|
||||
// This is probably safe, as we can usually bind just about
|
||||
// any supported texture format to the FBO.
|
||||
|
||||
// Rounding the depth bits is not spectacular, but at least we're
|
||||
// telling the user *something* about what we're going to get.
|
||||
|
|
@ -1286,6 +1249,9 @@ open_buffer() {
|
|||
if (_fb_properties.get_color_bits() == 0 &&
|
||||
_fb_properties.get_rgb_color()) {
|
||||
_fb_properties.set_color_bits(1);
|
||||
_fb_properties.set_red_bits(1);
|
||||
_fb_properties.set_green_bits(1);
|
||||
_fb_properties.set_blue_bits(1);
|
||||
}
|
||||
|
||||
// Actually, let's always get a colour buffer for now until we
|
||||
|
|
@ -1294,18 +1260,28 @@ open_buffer() {
|
|||
_fb_properties.set_color_bits(1);
|
||||
}
|
||||
|
||||
if (_fb_properties.get_depth_bits() >= 32) {
|
||||
if (_fb_properties.get_depth_bits() > 24) {
|
||||
_fb_properties.set_depth_bits(32);
|
||||
} else if (_fb_properties.get_depth_bits() > 16) {
|
||||
_fb_properties.set_depth_bits(24);
|
||||
} else if (_fb_properties.get_depth_bits() > 8) {
|
||||
} else {
|
||||
_fb_properties.set_depth_bits(16);
|
||||
}
|
||||
|
||||
// We're not going to get more than this, ever.
|
||||
// We're not going to get more than this, ever. At least not until OpenGL
|
||||
// introduces 64-bit texture formats.
|
||||
if (_fb_properties.get_color_bits() > 96) {
|
||||
_fb_properties.set_color_bits(96);
|
||||
}
|
||||
if (_fb_properties.get_red_bits() > 32) {
|
||||
_fb_properties.set_red_bits(32);
|
||||
}
|
||||
if (_fb_properties.get_green_bits() > 32) {
|
||||
_fb_properties.set_green_bits(32);
|
||||
}
|
||||
if (_fb_properties.get_blue_bits() > 32) {
|
||||
_fb_properties.set_blue_bits(32);
|
||||
}
|
||||
if (_fb_properties.get_alpha_bits() > 32) {
|
||||
_fb_properties.set_alpha_bits(32);
|
||||
}
|
||||
|
|
@ -1317,30 +1293,63 @@ open_buffer() {
|
|||
|
||||
// We currently only support color formats this big as float.
|
||||
if (_fb_properties.get_color_bits() > 16 * 3) {
|
||||
_fb_properties.set_color_bits(32 * 3);
|
||||
_fb_properties.set_float_color(true);
|
||||
|
||||
if (_fb_properties.get_alpha_bits() > 0) {
|
||||
_fb_properties.set_alpha_bits(32);
|
||||
}
|
||||
}
|
||||
|
||||
if (_fb_properties.get_srgb_color()) {
|
||||
_fb_properties.set_color_bits(24);
|
||||
// This is the only sRGB color format OpenGL supports.
|
||||
_fb_properties.set_rgba_bits(8, 8, 8,
|
||||
(_fb_properties.get_alpha_bits() > 0) ? 8 : 0);
|
||||
_fb_properties.set_float_color(false);
|
||||
|
||||
if (_fb_properties.get_alpha_bits() > 0) {
|
||||
_fb_properties.set_alpha_bits(32);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_gsg->get_supports_depth_stencil()) {
|
||||
// At least we know we won't be getting stencil bits.
|
||||
_fb_properties.set_stencil_bits(0);
|
||||
|
||||
} else if (_fb_properties.get_stencil_bits() > 0) {
|
||||
// We don't currently support stencil-only targets.
|
||||
_fb_properties.set_stencil_bits(8);
|
||||
if (_fb_properties.get_depth_bits() < 24) {
|
||||
_fb_properties.set_depth_bits(24);
|
||||
}
|
||||
}
|
||||
|
||||
// Accumulation buffers aren't supported for FBOs.
|
||||
_fb_properties.set_accum_bits(0);
|
||||
|
||||
if (glgsg->get_supports_framebuffer_multisample() && glgsg->get_supports_framebuffer_blit()) {
|
||||
_requested_multisamples = _fb_properties.get_multisamples();
|
||||
} else {
|
||||
_requested_multisamples = 0;
|
||||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
if (glgsg->get_supports_framebuffer_multisample_coverage_nv() && glgsg->get_supports_framebuffer_blit()) {
|
||||
_requested_coverage_samples = _fb_properties.get_coverage_samples();
|
||||
// Note: Only 4 and 8 actual samples are supported by the extension, with 8 or 16 coverage samples.
|
||||
if ((_requested_coverage_samples <= 8) && (_requested_coverage_samples > 0)) {
|
||||
_requested_multisamples = 4;
|
||||
_requested_coverage_samples = 8;
|
||||
} else if (_requested_coverage_samples > 8) {
|
||||
if (_requested_multisamples < 8) {
|
||||
_requested_multisamples = 4;
|
||||
} else {
|
||||
_requested_multisamples = 8;
|
||||
}
|
||||
_requested_coverage_samples = 16;
|
||||
}
|
||||
|
||||
} else {
|
||||
_requested_coverage_samples = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_requested_multisamples > glgsg->_max_fb_samples) {
|
||||
_requested_multisamples = glgsg->_max_fb_samples;
|
||||
}
|
||||
_fb_properties.set_multisamples(_requested_multisamples);
|
||||
_fb_properties.set_coverage_samples(_requested_coverage_samples);
|
||||
|
||||
// Update aux settings to reflect the GL_MAX_DRAW_BUFFERS limit,
|
||||
// if we exceed it, that is.
|
||||
|
|
|
|||
|
|
@ -1069,13 +1069,21 @@ issue_parameters(int altered) {
|
|||
case Shader::SMP_row3x3: _glgsg->_glUniform3fv(p, 1, data+12); continue;
|
||||
case Shader::SMP_upper3x3:
|
||||
{
|
||||
#ifndef STDFLOAT_DOUBLE
|
||||
LMatrix3f upper3 = val->get_upper_3();
|
||||
#else
|
||||
LMatrix3f upper3 = valf.get_upper_3();
|
||||
#endif
|
||||
_glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data());
|
||||
continue;
|
||||
}
|
||||
case Shader::SMP_transpose3x3:
|
||||
{
|
||||
#ifndef STDFLOAT_DOUBLE
|
||||
LMatrix3f upper3 = val->get_upper_3();
|
||||
#else
|
||||
LMatrix3f upper3 = valf.get_upper_3();
|
||||
#endif
|
||||
_glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data());
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,35 +136,28 @@ make_output(const string &name,
|
|||
// Second thing to try: a GLGraphicsBuffer
|
||||
|
||||
if (retry == 1) {
|
||||
if ((host==0)||
|
||||
(!gl_support_fbo)||
|
||||
((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
if (!gl_support_fbo || host == NULL ||
|
||||
(flags & (BF_require_parasite | BF_require_window)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Early failure - if we are sure that this buffer WONT
|
||||
// meet specs, we can bail out early.
|
||||
int _fbo_multisample = 0;
|
||||
if (!ConfigVariableBool("framebuffer-object-multisample", false, PRC_DESC("Enabled Multisample."))) {
|
||||
_fbo_multisample = 16;
|
||||
}
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
if ((fb_prop.get_indexed_color() > 0)||
|
||||
(fb_prop.get_back_buffers() > 0)||
|
||||
(fb_prop.get_accum_bits() > 0)||
|
||||
(fb_prop.get_multisamples() > _fbo_multisample)) {
|
||||
if ((flags & BF_fb_props_optional) == 0) {
|
||||
if (fb_prop.get_indexed_color() ||
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
if ((posixgsg != 0) &&
|
||||
(posixgsg->is_valid()) &&
|
||||
(!posixgsg->needs_reset()) &&
|
||||
(posixgsg->_supports_framebuffer_object) &&
|
||||
(posixgsg->_glDrawBuffers != 0)&&
|
||||
(fb_prop.is_basic())) {
|
||||
precertify = true;
|
||||
if (posixgsg != NULL && posixgsg->is_valid() && !posixgsg->needs_reset()) {
|
||||
if (!posixgsg->_supports_framebuffer_object ||
|
||||
posixgsg->_glDrawBuffers == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "pbitops.h"
|
||||
#include "streamReader.h"
|
||||
#include "texturePeeker.h"
|
||||
#include "convert_srgb.h"
|
||||
|
||||
#ifdef HAVE_SQUISH
|
||||
#include <squish.h>
|
||||
|
|
@ -131,46 +132,6 @@ struct DDSHeader {
|
|||
DDSCaps2 caps;
|
||||
};
|
||||
|
||||
// This table is used for converting unsigned char texture values in an sRGB
|
||||
// texture to linear RGB values, for use in mipmap generation.
|
||||
static float srgb_to_lrgbf[256] = {0.000000f, 0.000304f, 0.000607f, 0.000911f,
|
||||
0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
|
||||
0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f,
|
||||
0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f,
|
||||
0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f,
|
||||
0.014444f, 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f,
|
||||
0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f, 0.026241f,
|
||||
0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f,
|
||||
0.035601f, 0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f,
|
||||
0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, 0.054480f,
|
||||
0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f,
|
||||
0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f,
|
||||
0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
|
||||
0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f,
|
||||
0.114435f, 0.116971f, 0.119538f, 0.122139f, 0.124772f, 0.127438f, 0.130136f,
|
||||
0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f,
|
||||
0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f,
|
||||
0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f,
|
||||
0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f,
|
||||
0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f,
|
||||
0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f,
|
||||
0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f,
|
||||
0.309469f, 0.313989f, 0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f,
|
||||
0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
|
||||
0.376262f, 0.381326f, 0.386429f, 0.391572f, 0.396755f, 0.401978f, 0.407240f,
|
||||
0.412543f, 0.417885f, 0.423268f, 0.428690f, 0.434154f, 0.439657f, 0.445201f,
|
||||
0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473531f, 0.479320f, 0.485150f,
|
||||
0.491021f, 0.496933f, 0.502886f, 0.508881f, 0.514918f, 0.520996f, 0.527115f,
|
||||
0.533276f, 0.539479f, 0.545724f, 0.552011f, 0.558340f, 0.564712f, 0.571125f,
|
||||
0.577580f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f,
|
||||
0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f,
|
||||
0.672443f, 0.679542f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f,
|
||||
0.723055f, 0.730461f, 0.737910f, 0.745404f, 0.752942f, 0.760525f, 0.768151f,
|
||||
0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f, 0.822786f,
|
||||
0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
|
||||
0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f,
|
||||
0.947307f, 0.955973f, 0.964686f, 0.973445f, 0.982251f, 0.991102f, 1.000000f};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::Constructor
|
||||
// Access: Published
|
||||
|
|
@ -4436,7 +4397,7 @@ do_get_clear_data(const CData *cdata, unsigned char *into) const {
|
|||
switch (cdata->_component_type) {
|
||||
case T_unsigned_byte:
|
||||
{
|
||||
LColorf scaled = cdata->_clear_color.fmin(LColorf(1)).fmax(LColorf::zero());
|
||||
LColor scaled = cdata->_clear_color.fmin(LColor(1)).fmax(LColor::zero());
|
||||
scaled *= 255;
|
||||
switch (cdata->_num_components) {
|
||||
case 2:
|
||||
|
|
@ -4457,7 +4418,7 @@ do_get_clear_data(const CData *cdata, unsigned char *into) const {
|
|||
|
||||
case T_unsigned_short:
|
||||
{
|
||||
LColorf scaled = cdata->_clear_color.fmin(LColorf(1)).fmax(LColorf::zero());
|
||||
LColor scaled = cdata->_clear_color.fmin(LColor(1)).fmax(LColor::zero());
|
||||
scaled *= 65535;
|
||||
switch (cdata->_num_components) {
|
||||
case 2:
|
||||
|
|
@ -6990,7 +6951,13 @@ do_filter_2d_mipmap_pages(const CData *cdata,
|
|||
// We currently only support sRGB mipmap generation for
|
||||
// unsigned byte textures, due to our use of a lookup table.
|
||||
nassertv(cdata->_component_type == T_unsigned_byte);
|
||||
filter_component = &filter_2d_unsigned_byte_srgb;
|
||||
|
||||
if (has_sse2_sRGB_encode()) {
|
||||
filter_component = &filter_2d_unsigned_byte_srgb_sse2;
|
||||
} else {
|
||||
filter_component = &filter_2d_unsigned_byte_srgb;
|
||||
}
|
||||
|
||||
// Alpha is always linear.
|
||||
filter_alpha = &filter_2d_unsigned_byte;
|
||||
|
||||
|
|
@ -7140,7 +7107,13 @@ do_filter_3d_mipmap_level(const CData *cdata,
|
|||
// We currently only support sRGB mipmap generation for
|
||||
// unsigned byte textures, due to our use of a lookup table.
|
||||
nassertv(cdata->_component_type == T_unsigned_byte);
|
||||
filter_component = &filter_3d_unsigned_byte_srgb;
|
||||
|
||||
if (has_sse2_sRGB_encode()) {
|
||||
filter_component = &filter_3d_unsigned_byte_srgb_sse2;
|
||||
} else {
|
||||
filter_component = &filter_3d_unsigned_byte_srgb;
|
||||
}
|
||||
|
||||
// Alpha is always linear.
|
||||
filter_alpha = &filter_3d_unsigned_byte;
|
||||
|
||||
|
|
@ -7385,18 +7358,32 @@ filter_2d_unsigned_byte(unsigned char *&p, const unsigned char *&q,
|
|||
void Texture::
|
||||
filter_2d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size) {
|
||||
float result = (srgb_to_lrgbf[q[0]] +
|
||||
srgb_to_lrgbf[q[pixel_size]] +
|
||||
srgb_to_lrgbf[q[row_size]] +
|
||||
srgb_to_lrgbf[q[pixel_size + row_size]]) / 4.0f;
|
||||
float result = (decode_sRGB_float(q[0]) +
|
||||
decode_sRGB_float(q[pixel_size]) +
|
||||
decode_sRGB_float(q[row_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size]));
|
||||
|
||||
// This is based on the formula out of the EXT_texture_sRGB
|
||||
// specification, except the factors are multiplied with 255.0f.
|
||||
if (result < 0.0031308f) {
|
||||
*p = (unsigned char)(result * 3294.6f);
|
||||
} else {
|
||||
*p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f);
|
||||
}
|
||||
*p = encode_sRGB_uchar(result * 0.25f);
|
||||
++p;
|
||||
++q;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::filter_2d_unsigned_byte_srgb_sse2
|
||||
// Access: Public, Static
|
||||
// Description: Averages a 2x2 block of pixel components into a
|
||||
// single pixel component, for producing the next mipmap
|
||||
// level. Increments p and q to the next component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
filter_2d_unsigned_byte_srgb_sse2(unsigned char *&p, const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size) {
|
||||
float result = (decode_sRGB_float(q[0]) +
|
||||
decode_sRGB_float(q[pixel_size]) +
|
||||
decode_sRGB_float(q[row_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size]));
|
||||
|
||||
*p = encode_sRGB_uchar_sse2(result * 0.25f);
|
||||
++p;
|
||||
++q;
|
||||
}
|
||||
|
|
@ -7470,22 +7457,40 @@ filter_3d_unsigned_byte(unsigned char *&p, const unsigned char *&q,
|
|||
void Texture::
|
||||
filter_3d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size, size_t page_size) {
|
||||
float result = (srgb_to_lrgbf[q[0]] +
|
||||
srgb_to_lrgbf[q[pixel_size]] +
|
||||
srgb_to_lrgbf[q[row_size]] +
|
||||
srgb_to_lrgbf[q[pixel_size + row_size]] +
|
||||
srgb_to_lrgbf[q[page_size]] +
|
||||
srgb_to_lrgbf[q[pixel_size + page_size]] +
|
||||
srgb_to_lrgbf[q[row_size + page_size]] +
|
||||
srgb_to_lrgbf[q[pixel_size + row_size + page_size]]) / 8.0f;
|
||||
float result = (decode_sRGB_float(q[0]) +
|
||||
decode_sRGB_float(q[pixel_size]) +
|
||||
decode_sRGB_float(q[row_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size]) +
|
||||
decode_sRGB_float(q[page_size]) +
|
||||
decode_sRGB_float(q[pixel_size + page_size]) +
|
||||
decode_sRGB_float(q[row_size + page_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size + page_size]));
|
||||
|
||||
// This is based on the formula out of the EXT_texture_sRGB
|
||||
// specification, except the factors are multiplied with 255.0f.
|
||||
if (result < 0.0031308f) {
|
||||
*p = (unsigned char)(result * 3294.6f);
|
||||
} else {
|
||||
*p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f);
|
||||
}
|
||||
*p = encode_sRGB_uchar(result * 0.125f);
|
||||
++p;
|
||||
++q;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::filter_3d_unsigned_byte_srgb_sse2
|
||||
// Access: Public, Static
|
||||
// Description: Averages a 2x2x2 block of pixel components into a
|
||||
// single pixel component, for producing the next mipmap
|
||||
// level. Increments p and q to the next component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
filter_3d_unsigned_byte_srgb_sse2(unsigned char *&p, const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size, size_t page_size) {
|
||||
float result = (decode_sRGB_float(q[0]) +
|
||||
decode_sRGB_float(q[pixel_size]) +
|
||||
decode_sRGB_float(q[row_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size]) +
|
||||
decode_sRGB_float(q[page_size]) +
|
||||
decode_sRGB_float(q[pixel_size + page_size]) +
|
||||
decode_sRGB_float(q[row_size + page_size]) +
|
||||
decode_sRGB_float(q[pixel_size + row_size + page_size]));
|
||||
|
||||
*p = encode_sRGB_uchar_sse2(result * 0.125f);
|
||||
++p;
|
||||
++q;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -752,6 +752,9 @@ private:
|
|||
static void filter_2d_unsigned_byte_srgb(unsigned char *&p,
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size);
|
||||
static void filter_2d_unsigned_byte_srgb_sse2(unsigned char *&p,
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size);
|
||||
static void filter_2d_unsigned_short(unsigned char *&p,
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size);
|
||||
|
|
@ -766,6 +769,10 @@ private:
|
|||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size,
|
||||
size_t page_size);
|
||||
static void filter_3d_unsigned_byte_srgb_sse2(unsigned char *&p,
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size,
|
||||
size_t page_size);
|
||||
static void filter_3d_unsigned_short(unsigned char *&p,
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size,
|
||||
|
|
|
|||
|
|
@ -57,11 +57,11 @@ void PfmVizzer::
|
|||
project(const Lens *lens, const PfmFile *undist_lut) {
|
||||
nassertv(_pfm.is_valid());
|
||||
|
||||
static LMatrix4f to_uv(0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
static LMatrix4 to_uv(0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
for (int yi = 0; yi < _pfm.get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < _pfm.get_x_size(); ++xi) {
|
||||
if (!_pfm.has_point(xi, yi)) {
|
||||
|
|
@ -79,8 +79,8 @@ project(const Lens *lens, const PfmFile *undist_lut) {
|
|||
} else {
|
||||
// Now the lens gives us coordinates in the range [-1, 1].
|
||||
// Rescale these to [0, 1].
|
||||
LPoint3f uvw = film * to_uv;
|
||||
|
||||
LPoint3f uvw = LCAST(float, film * to_uv);
|
||||
|
||||
if (undist_lut != NULL) {
|
||||
// Apply the undistortion map, if given.
|
||||
LPoint3f p2;
|
||||
|
|
@ -88,7 +88,7 @@ project(const Lens *lens, const PfmFile *undist_lut) {
|
|||
uvw = p2;
|
||||
uvw[1] = 1.0 - uvw[1];
|
||||
}
|
||||
|
||||
|
||||
p = uvw;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
INLINE void OdeRayGeom::
|
||||
set_length(dReal length) {
|
||||
dGeomRaySetLength(_id, length);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ PUBLISHED:
|
|||
// INLINE void get_buffer(unsigned char** buf, int* buf_len) const;
|
||||
// INLINE void set_buffer(unsigned char* buf);
|
||||
// INLINE void update();
|
||||
|
||||
virtual void write(ostream &out = cout, unsigned int indent=0) const;
|
||||
void write_faces(ostream &out) const;
|
||||
|
||||
|
|
@ -90,6 +91,7 @@ public:
|
|||
const int* indices, int index_count, \
|
||||
const int* normals);
|
||||
*/
|
||||
|
||||
INLINE void preprocess();
|
||||
|
||||
INLINE dTriMeshDataID get_id() const;
|
||||
|
|
|
|||
|
|
@ -412,37 +412,32 @@ make_output(const string &name,
|
|||
return new osxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
|
||||
// Second thing to try: a GLGraphicsBuffer
|
||||
|
||||
|
||||
if (retry == 1) {
|
||||
if (!osx_support_gl_buffer) {
|
||||
return NULL;
|
||||
}
|
||||
if ((host==0)||
|
||||
((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
if (!osx_support_gl_buffer || !gl_support_fbo || host == NULL ||
|
||||
(flags & (BF_require_parasite | BF_require_window)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Early failure - if we are sure that this buffer WONT
|
||||
// meet specs, we can bail out early.
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
if ((fb_prop.get_indexed_color() > 0)||
|
||||
(fb_prop.get_back_buffers() > 0)||
|
||||
(fb_prop.get_accum_bits() > 0)||
|
||||
(fb_prop.get_multisamples() > 0)) {
|
||||
if ((flags & BF_fb_props_optional) == 0) {
|
||||
if (fb_prop.get_indexed_color() ||
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
if ((osxgsg != 0) &&
|
||||
(osxgsg->is_valid()) &&
|
||||
(!osxgsg->needs_reset()) &&
|
||||
(osxgsg->_supports_framebuffer_object) &&
|
||||
(osxgsg->_glDrawBuffers != 0)&&
|
||||
(fb_prop.is_basic())) {
|
||||
precertify = true;
|
||||
if (posixgsg != NULL && posixgsg->is_valid() && !posixgsg->needs_reset()) {
|
||||
if (!posixgsg->_supports_framebuffer_object ||
|
||||
posixgsg->_glDrawBuffers == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ private:
|
|||
class EXPCL_PANDA_PGRAPH BinDefinition {
|
||||
public:
|
||||
#ifndef NDEBUG
|
||||
LColorf _flash_color;
|
||||
LColor _flash_color;
|
||||
bool _flash_active;
|
||||
#endif
|
||||
bool _in_use;
|
||||
|
|
|
|||
|
|
@ -721,13 +721,15 @@ get_user_bounds(int pipeline_stage, Thread *current_thread) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaNode::
|
||||
mark_bounds_stale(int pipeline_stage, Thread *current_thread) const {
|
||||
// It's important that we don't hold the lock during the call to
|
||||
// force_bounds_stale().
|
||||
// We check whether it is already marked stale. If so, we don't have
|
||||
// to make the call to force_bounds_stale().
|
||||
bool is_stale_bounds;
|
||||
{
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
is_stale_bounds = (cdata->_last_bounds_update != cdata->_next_update);
|
||||
is_stale_bounds = (cdata->_last_update != cdata->_next_update);
|
||||
}
|
||||
// It's important that we don't hold the lock during the call to
|
||||
// force_bounds_stale().
|
||||
if (!is_stale_bounds) {
|
||||
((PandaNode *)this)->force_bounds_stale(pipeline_stage, current_thread);
|
||||
}
|
||||
|
|
@ -1833,7 +1835,7 @@ get_off_clip_planes() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(BoundingVolume) PandaNodePipelineReader::
|
||||
get_bounds() const {
|
||||
nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_external_bounds);
|
||||
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
|
||||
return _cdata->_external_bounds;
|
||||
}
|
||||
|
||||
|
|
@ -1852,7 +1854,7 @@ get_bounds() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PandaNodePipelineReader::
|
||||
get_nested_vertices() const {
|
||||
nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_nested_vertices);
|
||||
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_nested_vertices);
|
||||
return _cdata->_nested_vertices;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,175 @@
|
|||
// Filename: convert_srgb.I
|
||||
// Created by: rdb (29Oct14)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: decode_sRGB_float
|
||||
// Description: Decodes the sRGB-encoded unsigned char value to
|
||||
// a linearized float in the range 0-1.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CONSTEXPR float decode_sRGB_float(unsigned char val) {
|
||||
return to_linear_float_table[val];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_float
|
||||
// Description: Decodes the sRGB-encoded floating-point value in
|
||||
// the range 0-1 to a linearized float in the range
|
||||
// 0-1. Inputs outside this range produce invalid
|
||||
// results.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float decode_sRGB_float(float val) {
|
||||
return (val <= 0.04045f)
|
||||
? (val * (1.f / 12.92f))
|
||||
: cpow((val + 0.055f) * (1.f / 1.055f), 2.4f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: decode_sRGB_uchar
|
||||
// Description: Decodes the sRGB-encoded unsigned char value to
|
||||
// a linearized unsigned char value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CONSTEXPR unsigned char decode_sRGB_uchar(unsigned char val) {
|
||||
return to_linear_uchar_table[val];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: decode_sRGB_uchar
|
||||
// Description: Decodes the sRGB-encoded floating-point value in
|
||||
// the range 0-1 to a linearized unsigned char value.
|
||||
// Inputs outside this range are clamped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE unsigned char decode_sRGB_uchar(float val) {
|
||||
return (val <= 0.04045f)
|
||||
? (unsigned char)(max(0.f, val) * (255.f / 12.92f) + 0.5f)
|
||||
: (unsigned char)(cpow((min(val, 1.f) + 0.055f) * (1.f / 1.055f), 2.4f) * 255.f + 0.5f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_float
|
||||
// Description: Encodes the linearized unsigned char value to an
|
||||
// sRGB-encoded floating-point value in ther range 0-1.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float
|
||||
encode_sRGB_float(unsigned char val) {
|
||||
// This seems like a very unlikely use case, so I didn't bother
|
||||
// making a look-up table for this.
|
||||
return (val == 0) ? 0
|
||||
: (1.055f * cpow((float)val * (1.f / 255.f), 0.41666f) - 0.055);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_float
|
||||
// Description: Encodes the linearized floating-point value in the
|
||||
// range 0-1 to an sRGB-encoded float in the range
|
||||
// 0-1. Inputs outside this range produce invalid
|
||||
// results.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float
|
||||
encode_sRGB_float(float val) {
|
||||
return (val < 0.0031308f)
|
||||
? (val * 12.92f)
|
||||
: (1.055f * cpow(val, 0.41666f) - 0.055);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_uchar
|
||||
// Description: Encodes the linearized unsigned char value to an
|
||||
// sRGB-encoded unsigned char value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CONSTEXPR unsigned char
|
||||
encode_sRGB_uchar(unsigned char val) {
|
||||
return to_srgb8_table[val];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_uchar
|
||||
// Description: Encodes the linearized floating-point value in the
|
||||
// range 0-1 to an sRGB-encoded unsigned char value.
|
||||
// Inputs outside this range are clamped.
|
||||
//
|
||||
// When SSE2 support is known at compile time, this
|
||||
// automatically uses an optimized version. Otherwise,
|
||||
// it does not attempt runtime CPU detection. If you
|
||||
// know that SSE2 is supported (ie. if the function
|
||||
// has_sse2_sRGB_encode() returns true) you should
|
||||
// call encode_sRGB_uchar_sse2 instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE unsigned char
|
||||
encode_sRGB_uchar(float val) {
|
||||
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
|
||||
// Use a highly optimized approximation that has more than enough
|
||||
// accuracy for an unsigned char.
|
||||
return encode_sRGB_uchar_sse2(val);
|
||||
#else
|
||||
return (val < 0.0031308f)
|
||||
? (unsigned char) (max(0.f, val) * 3294.6f + 0.5f)
|
||||
: (unsigned char) (269.025f * cpow(min(val, 1.f), 0.41666f) - 13.525f);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_uchar
|
||||
// Description: Encodes the linearized floating-point color value
|
||||
// an sRGB-encoded xel in the range 0-255.
|
||||
//
|
||||
// When SSE2 support is known at compile time, this
|
||||
// automatically uses an optimized version. Otherwise,
|
||||
// it does not attempt runtime CPU detection. If you
|
||||
// know that SSE2 is supported (ie. if the function
|
||||
// has_sse2_sRGB_encode() returns true) you should
|
||||
// call encode_sRGB_uchar_sse2 instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
encode_sRGB_uchar(const LColorf &color, xel &into) {
|
||||
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
|
||||
// SSE2 support compiled-in; we're guaranteed to have it.
|
||||
encode_sRGB_uchar_sse2(color, into);
|
||||
#else
|
||||
// Boring, slow, non-SSE2 version.
|
||||
PPM_ASSIGN(into,
|
||||
encode_sRGB_uchar(color[0]),
|
||||
encode_sRGB_uchar(color[1]),
|
||||
encode_sRGB_uchar(color[2]));
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: encode_sRGB_uchar
|
||||
// Description: Encodes the linearized floating-point color value
|
||||
// an sRGB-encoded xel and alpha in the range 0-255.
|
||||
// The alpha value is not sRGB-encoded.
|
||||
//
|
||||
// When SSE2 support is known at compile time, this
|
||||
// automatically uses an optimized version. Otherwise,
|
||||
// it does not attempt runtime CPU detection. If you
|
||||
// know that SSE2 is supported (ie. if the function
|
||||
// has_sse2_sRGB_encode() returns true) you should
|
||||
// call encode_sRGB_uchar_sse2 instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
encode_sRGB_uchar(const LColorf &color, xel &into, xelval &into_alpha) {
|
||||
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
|
||||
// SSE2 support compiled-in; we're guaranteed to have it.
|
||||
encode_sRGB_uchar_sse2(color, into, into_alpha);
|
||||
#else
|
||||
// Boring, slow, non-SSE2 version.
|
||||
PPM_ASSIGN(into,
|
||||
encode_sRGB_uchar(color[0]),
|
||||
encode_sRGB_uchar(color[1]),
|
||||
encode_sRGB_uchar(color[2]));
|
||||
|
||||
into_alpha = (xelval) (color[3] * 255.f + 0.5f);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// Filename: convert_srgb.cxx
|
||||
// Created by: rdb (13Nov14)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "convert_srgb.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// Lookup tables for converting from unsigned char formats.
|
||||
ALIGN_64BYTE const
|
||||
unsigned char to_srgb8_table[256] = { 0x00, 0x0d, 0x16, 0x1c, 0x22, 0x26, 0x2a,
|
||||
0x2e, 0x32, 0x35, 0x38, 0x3b, 0x3d, 0x40, 0x42, 0x45, 0x47, 0x49, 0x4b, 0x4d,
|
||||
0x4f, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63,
|
||||
0x65, 0x66, 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, 0x71, 0x72, 0x73, 0x75,
|
||||
0x76, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
|
||||
0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b,
|
||||
0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6,
|
||||
0xa7, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xaf, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb9,
|
||||
0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1,
|
||||
0xc2, 0xc2, 0xc3, 0xc4, 0xc4, 0xc5, 0xc5, 0xc6, 0xc7, 0xc7, 0xc8, 0xc8, 0xc9,
|
||||
0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf, 0xd0, 0xd0, 0xd1,
|
||||
0xd1, 0xd2, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8,
|
||||
0xd8, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xde, 0xdf,
|
||||
0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6,
|
||||
0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, 0xec,
|
||||
0xed, 0xed, 0xee, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2,
|
||||
0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8,
|
||||
0xf9, 0xf9, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe,
|
||||
0xff, 0xff};
|
||||
|
||||
ALIGN_64BYTE const
|
||||
unsigned char to_linear_uchar_table[256] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07,
|
||||
0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b,
|
||||
0x0b, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10,
|
||||
0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
|
||||
0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e,
|
||||
0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
|
||||
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4c, 0x4d,
|
||||
0x4e, 0x4f, 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5c,
|
||||
0x5d, 0x5f, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6c, 0x6d,
|
||||
0x6f, 0x70, 0x72, 0x73, 0x74, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, 0x80,
|
||||
0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x92, 0x93, 0x95,
|
||||
0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9f, 0xa1, 0xa3, 0xa4, 0xa6, 0xa8, 0xaa, 0xab,
|
||||
0xad, 0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, 0xc4,
|
||||
0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
|
||||
0xe0, 0xe2, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa,
|
||||
0xfd, 0xff};
|
||||
|
||||
ALIGN_64BYTE
|
||||
const float to_linear_float_table[256] = { 0, 0.000304f, 0.000607f, 0.000911f,
|
||||
0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
|
||||
0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f,
|
||||
0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f,
|
||||
0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f,
|
||||
0.014444f, 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f,
|
||||
0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f, 0.026241f,
|
||||
0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f,
|
||||
0.035601f, 0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f,
|
||||
0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, 0.054480f,
|
||||
0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f,
|
||||
0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f,
|
||||
0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
|
||||
0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f,
|
||||
0.114435f, 0.116971f, 0.119538f, 0.122139f, 0.124772f, 0.127438f, 0.130136f,
|
||||
0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f,
|
||||
0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f,
|
||||
0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f,
|
||||
0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f,
|
||||
0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f,
|
||||
0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f,
|
||||
0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f,
|
||||
0.309469f, 0.313989f, 0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f,
|
||||
0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
|
||||
0.376262f, 0.381326f, 0.386429f, 0.391572f, 0.396755f, 0.401978f, 0.407240f,
|
||||
0.412543f, 0.417885f, 0.423268f, 0.428690f, 0.434154f, 0.439657f, 0.445201f,
|
||||
0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473531f, 0.479320f, 0.485150f,
|
||||
0.491021f, 0.496933f, 0.502886f, 0.508881f, 0.514918f, 0.520996f, 0.527115f,
|
||||
0.533276f, 0.539479f, 0.545724f, 0.552011f, 0.558340f, 0.564712f, 0.571125f,
|
||||
0.577580f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f,
|
||||
0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f,
|
||||
0.672443f, 0.679542f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f,
|
||||
0.723055f, 0.730461f, 0.737910f, 0.745404f, 0.752942f, 0.760525f, 0.768151f,
|
||||
0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f, 0.822786f,
|
||||
0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
|
||||
0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f,
|
||||
0.947307f, 0.955973f, 0.964686f, 0.973445f, 0.982251f, 0.991102f, 1.000000f};
|
||||
|
||||
|
||||
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
|
||||
// SSE2 support enabled at compile time. No runtime detection mechanism needed.
|
||||
bool
|
||||
has_sse2_sRGB_encode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
// SSE2 support not guaranteed. Use a runtime detection mechanism.
|
||||
|
||||
bool
|
||||
has_sse2_sRGB_encode() {
|
||||
#if defined(__GNUC__)
|
||||
unsigned int a, b, c, d;
|
||||
static const bool has_support =
|
||||
(__get_cpuid(1, &a, &b, &c, &d) == 1 && (d & 0x04000000) != 0);
|
||||
|
||||
#elif defined(_WIN32)
|
||||
static const bool has_support =
|
||||
(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) != FALSE);
|
||||
|
||||
#else
|
||||
static const bool has_support = false;
|
||||
#endif
|
||||
|
||||
if (pnmimage_cat.is_debug()) {
|
||||
static bool checked = false;
|
||||
if (!checked) {
|
||||
#if defined(__GNUC__) || defined(_WIN32)
|
||||
if (has_support) {
|
||||
pnmimage_cat.debug()
|
||||
<< "Runtime detection reports SSE2 instructions available: "
|
||||
<< "SSE2-optimized sRGB encoding routines enabled.\n";
|
||||
} else {
|
||||
pnmimage_cat.debug()
|
||||
<< "Runtime detection reports SSE2 instructions unavailable: "
|
||||
<< "SSE2-optimized sRGB encoding routines disabled.\n";
|
||||
}
|
||||
#else
|
||||
pnmimage_cat.debug()
|
||||
<< "No runtime detection mechanism for SSE2 instructions available: "
|
||||
<< "SSE2-optimized sRGB encoding routines disabled.\n";
|
||||
#endif
|
||||
checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
return has_support;
|
||||
}
|
||||
|
||||
#endif // __SSE2__
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Filename: convert_srgb.h
|
||||
// Created by: rdb (13Nov14)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONVERT_SRGB_H
|
||||
#define CONVERT_SRGB_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "luse.h"
|
||||
#include "pnmimage_base.h"
|
||||
|
||||
// The below functions can encode and decode sRGB colors in various
|
||||
// representations. Some of them are implemented using look-up tables,
|
||||
// some others using SSE2 intrinsics.
|
||||
extern EXPCL_PANDA_PNMIMAGE const unsigned char to_srgb8_table[256];
|
||||
extern EXPCL_PANDA_PNMIMAGE const unsigned char to_linear_uchar_table[256];
|
||||
extern EXPCL_PANDA_PNMIMAGE const float to_linear_float_table[256];
|
||||
|
||||
EXPCL_PANDA_PNMIMAGE CONSTEXPR float decode_sRGB_float(unsigned char val);
|
||||
EXPCL_PANDA_PNMIMAGE INLINE float decode_sRGB_float(float val);
|
||||
EXPCL_PANDA_PNMIMAGE CONSTEXPR unsigned char decode_sRGB_uchar(unsigned char val);
|
||||
EXPCL_PANDA_PNMIMAGE INLINE unsigned char decode_sRGB_uchar(float val);
|
||||
|
||||
EXPCL_PANDA_PNMIMAGE INLINE float encode_sRGB_float(unsigned char val);
|
||||
EXPCL_PANDA_PNMIMAGE INLINE float encode_sRGB_float(float val);
|
||||
EXPCL_PANDA_PNMIMAGE CONSTEXPR unsigned char encode_sRGB_uchar(unsigned char val);
|
||||
EXPCL_PANDA_PNMIMAGE INLINE unsigned char encode_sRGB_uchar(float val);
|
||||
|
||||
// These functions convert more than one component in one go,
|
||||
// which can be faster due to vectorization.
|
||||
EXPCL_PANDA_PNMIMAGE INLINE void encode_sRGB_uchar(const LColorf &from,
|
||||
xel &into);
|
||||
EXPCL_PANDA_PNMIMAGE INLINE void encode_sRGB_uchar(const LColorf &from,
|
||||
xel &into, xelval &into_alpha);
|
||||
|
||||
// Use these functions if you know that SSE2 support is available.
|
||||
// Otherwise, they will crash!
|
||||
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar_sse2(float val);
|
||||
EXPCL_PANDA_PNMIMAGE void encode_sRGB_uchar_sse2(const LColorf &from,
|
||||
xel &into);
|
||||
EXPCL_PANDA_PNMIMAGE void encode_sRGB_uchar_sse2(const LColorf &from,
|
||||
xel &into, xelval &into_alpha);
|
||||
|
||||
// Use the following to find out if you can call either of the above.
|
||||
EXPCL_PANDA_PNMIMAGE bool has_sse2_sRGB_encode();
|
||||
|
||||
#include "convert_srgb.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
// Filename: convert_srgb_sse2.cxx
|
||||
// Created by: rdb (13Nov14)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file should always be compiled with SSE2 support. These
|
||||
// functions will only be called when SSE2 support is detected at
|
||||
// run-time.
|
||||
|
||||
#include "convert_srgb.h"
|
||||
#include "luse.h"
|
||||
|
||||
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
static INLINE __m128i _encode_sRGB_sse2_mul255(__m128 val) {
|
||||
// This an SSE2-based approximation of the sRGB encode function.
|
||||
// It has a maximum error of around 0.001, which is by far small
|
||||
// enough for a uchar. It is also at least 10x as fast as the
|
||||
// original; up to 40x when taking advantage of vectorization.
|
||||
// Note that the fourth float is only multiplied with 255.
|
||||
|
||||
// Part of the code in this function is derived from:
|
||||
// http://stackoverflow.com/a/6486630/2135754
|
||||
|
||||
// Clamp to 0-1 range.
|
||||
val = _mm_max_ps(val, _mm_set1_ps(0.0f));
|
||||
val = _mm_min_ps(val, _mm_set1_ps(1.0f));
|
||||
|
||||
// Pre-multiply with constant factor to adjust for exp bias.
|
||||
__m128 xf = _mm_mul_ps(val, _mm_set1_ps(6.3307e18f));
|
||||
|
||||
// Approximate logarithm by... casting!
|
||||
xf = _mm_cvtepi32_ps(_mm_castps_si128(xf));
|
||||
|
||||
// Multiply 'logarithm' by power.
|
||||
xf = _mm_mul_ps(xf, _mm_set1_ps(2.0f / 3.0f));
|
||||
|
||||
// Reverse operation of above: cast the other way.
|
||||
xf = _mm_castsi128_ps(_mm_cvtps_epi32(xf));
|
||||
|
||||
// Make an overestimate and an underestimate.
|
||||
__m128 xover = _mm_mul_ps(val, xf);
|
||||
__m128 xunder = _mm_mul_ps(_mm_mul_ps(val, val),
|
||||
_mm_rsqrt_ps(xf));
|
||||
|
||||
// Average the two factors, with a slight bias.
|
||||
__m128 xavg = _mm_mul_ps(_mm_add_ps(xover, xunder),
|
||||
_mm_set1_ps(0.5286098f));
|
||||
|
||||
// Take square root twice. Note that this is faster than
|
||||
// the more expensive _mm_sqrt_ps instruction.
|
||||
xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg));
|
||||
xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg));
|
||||
|
||||
// Bring it into the correct range. These factors are determined
|
||||
// not on the basis of accuracy, but are chosen such that the
|
||||
// decoder lookup table produces an equivalent result for any value.
|
||||
xavg = _mm_mul_ps(xavg, _mm_set1_ps(269.122f));
|
||||
xavg = _mm_sub_ps(xavg, _mm_set1_ps(13.55f));
|
||||
|
||||
// Compute the linear section. This is also the path that
|
||||
// the alpha channel takes, so we set the alpha multiplier
|
||||
// to 255 (since alpha is not sRGB-converted).
|
||||
__m128 lval = _mm_mul_ps(val,
|
||||
_mm_set_ps(255.0f, 3294.6f, 3294.6f, 3294.6f));
|
||||
|
||||
lval = _mm_add_ps(lval, _mm_set1_ps(0.5f));
|
||||
|
||||
// Decide which version to return. Rig the alpha
|
||||
// comparator to always fail so that the linear path
|
||||
// is always chosen for alpha.
|
||||
__m128 mask = _mm_cmpge_ps(val,
|
||||
_mm_set_ps(2.0f, 0.0031308f, 0.0031308f, 0.0031308f));
|
||||
|
||||
// This is a non-branching way to return one or the other value.
|
||||
return _mm_cvttps_epi32(_mm_or_ps(
|
||||
_mm_and_ps(mask, xavg),
|
||||
_mm_andnot_ps(mask, lval)));
|
||||
}
|
||||
|
||||
unsigned char
|
||||
encode_sRGB_uchar_sse2(float val) {
|
||||
// Running only a single component through this function is still
|
||||
// way faster than the equivalent non-SSE2 version.
|
||||
return (unsigned char)
|
||||
_mm_extract_epi16(_encode_sRGB_sse2_mul255(_mm_set1_ps(val)), 0);
|
||||
}
|
||||
|
||||
void
|
||||
encode_sRGB_uchar_sse2(const LColorf &color, xel &into) {
|
||||
#ifdef LINMATH_ALIGN
|
||||
__m128 vec = _mm_load_ps(color.get_data());
|
||||
#else
|
||||
__m128 vec = _mm_loadu_ps(color.get_data());
|
||||
#endif
|
||||
|
||||
__m128i vals = _encode_sRGB_sse2_mul255(vec);
|
||||
into.r = _mm_extract_epi16(vals, 0);
|
||||
into.g = _mm_extract_epi16(vals, 2);
|
||||
into.b = _mm_extract_epi16(vals, 4);
|
||||
}
|
||||
|
||||
void
|
||||
encode_sRGB_uchar_sse2(const LColorf &color, xel &into, xelval &into_alpha) {
|
||||
#ifdef LINMATH_ALIGN
|
||||
__m128 vec = _mm_load_ps(color.get_data());
|
||||
#else
|
||||
__m128 vec = _mm_loadu_ps(color.get_data());
|
||||
#endif
|
||||
|
||||
__m128i vals = _encode_sRGB_sse2_mul255(vec);
|
||||
into.r = _mm_extract_epi16(vals, 0);
|
||||
into.g = _mm_extract_epi16(vals, 2);
|
||||
into.b = _mm_extract_epi16(vals, 4);
|
||||
into_alpha = _mm_extract_epi16(vals, 6);
|
||||
}
|
||||
|
||||
#else
|
||||
// Somehow we're still compiling this without SSE2 support. We'll
|
||||
// still have to define these functions, but emit a warning that the
|
||||
// build system isn't configured properly.
|
||||
#warning convert_srgb_sse2.cxx is being compiled without SSE2 support!
|
||||
|
||||
unsigned char
|
||||
encode_sRGB_uchar_sse2(float val) {
|
||||
return encode_sRGB_uchar(val);
|
||||
}
|
||||
|
||||
void
|
||||
encode_sRGB_uchar_sse2(const LColorf &color, xel &into) {
|
||||
encode_sRGB_uchar(color, into);
|
||||
}
|
||||
|
||||
void
|
||||
encode_sRGB_uchar_sse2(const LColorf &color, xel &into, xelval &into_alpha) {
|
||||
encode_sRGB_uchar(color, into, into_alpha);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "config_pnmimage.cxx"
|
||||
#include "convert_srgb.cxx"
|
||||
#include "pfmFile.cxx"
|
||||
#include "pnm-image-filter.cxx"
|
||||
#include "pnmbitio.cxx"
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ private:
|
|||
|
||||
// Hold the scissor settings and whether or not to enable scissoring.
|
||||
bool _enable_scissor;
|
||||
LVecBase4f _scissor;
|
||||
LVecBase4 _scissor;
|
||||
|
||||
// These are temporarily filled in by render().
|
||||
CullTraverser *_trav;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ typedef unsigned int ZPOINT;
|
|||
((((unsigned int)(a) << 24) & 0xff000000) | (((unsigned int)(r) << 16) & 0xff0000) | (((unsigned int)(g) << 8) & 0xff00) | (unsigned int)(b))
|
||||
|
||||
#define SRGB_TO_PIXEL(r,g,b) \
|
||||
((encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB10[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))
|
||||
((encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))
|
||||
#define SRGBA_TO_PIXEL(r,g,b,a) \
|
||||
((((unsigned int)(a) << 16) & 0xff000000) | (encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))
|
||||
|
||||
|
|
|
|||
|
|
@ -153,46 +153,32 @@ make_output(const string &name,
|
|||
return new wglGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
|
||||
// Second thing to try: a GLGraphicsBuffer
|
||||
|
||||
|
||||
if (retry == 1) {
|
||||
if ((!gl_support_fbo)||
|
||||
(host==0)||
|
||||
((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
if (!gl_support_fbo || host == NULL ||
|
||||
(flags & (BF_require_parasite | BF_require_window)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Early failure - if we are sure that this buffer WONT
|
||||
// meet specs, we can bail out early.
|
||||
int _fbo_multisample = 0;
|
||||
if (!ConfigVariableBool("framebuffer-object-multisample", false, PRC_DESC("Enabled Multisample."))) {
|
||||
_fbo_multisample = 16;
|
||||
}
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
if ((flags & BF_fb_props_optional) == 0) {
|
||||
if (fb_prop.get_indexed_color() ||
|
||||
(fb_prop.get_back_buffers() > 0)||
|
||||
(fb_prop.get_accum_bits() > 0)||
|
||||
(fb_prop.get_multisamples() > _fbo_multisample)) {
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if ((wglgsg != 0) &&
|
||||
(wglgsg->is_valid()) &&
|
||||
(!wglgsg->needs_reset()) &&
|
||||
!wglgsg->_supports_framebuffer_object) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
if ((wglgsg != 0) &&
|
||||
(wglgsg->is_valid()) &&
|
||||
(!wglgsg->needs_reset()) &&
|
||||
(wglgsg->_supports_framebuffer_object) &&
|
||||
(wglgsg->_glDrawBuffers != 0)&&
|
||||
(fb_prop.is_basic())) {
|
||||
precertify = true;
|
||||
if (wglgsg != NULL && wglgsg->is_valid() && !wglgsg->needs_reset()) {
|
||||
if (!wglgsg->_supports_framebuffer_object ||
|
||||
wglgsg->_glDrawBuffers == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &keys) {
|
|||
}
|
||||
|
||||
// Quantize the FPS, otherwise Panda complains about FPS mismatches.
|
||||
float fps = round(((keys.size() - 1) / timing_total) * 100) * 0.01f;
|
||||
float fps = cfloor(((keys.size() - 1) / timing_total) * 100 + 0.5f) * 0.01f;
|
||||
xform->set_fps(fps);
|
||||
|
||||
// Loop through the children joints
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
_bind_pose(LMatrix4d::ident_mat()) {}
|
||||
|
||||
LMatrix4d _bind_pose;
|
||||
const PT(EggGroup) _group;
|
||||
PT(EggGroup) _group;
|
||||
const FCDSceneNode *_scene_node;
|
||||
DaeCharacter *_character;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ convert_file(const Filename &filename) {
|
|||
Characters::iterator it;
|
||||
DaeCharacter *character;
|
||||
for (it = _characters.begin(); it != _characters.end(); ++it) {
|
||||
DaeCharacter *character = *it;
|
||||
character = *it;
|
||||
|
||||
// Collect key frame timings.
|
||||
if (get_animation_convert() == AC_both ||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@
|
|||
#error You must include pre_fcollada_include.h before including FCollada.h!
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
// FCollada expects LINUX to be defined on linux
|
||||
#ifdef IS_LINUX
|
||||
#ifndef LINUX
|
||||
|
|
|
|||
|
|
@ -0,0 +1,399 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Author: Shao Zhang, Phil Saltzman, and Greg Lindley
|
||||
# Last Updated: 2015-03-13
|
||||
#
|
||||
# This tutorial demonstrates the use of tasks. A task is a function that
|
||||
# gets called once every frame. They are good for things that need to be
|
||||
# updated very often. In the case of asteroids, we use tasks to update
|
||||
# the positions of all the objects, and to check if the bullets or the
|
||||
# ship have hit the asteroids.
|
||||
#
|
||||
# Note: This definitely a complicated example. Tasks are the cores of
|
||||
# most games so it seemed appropriate to show what a full game in Panda
|
||||
# could look like.
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from panda3d.core import TextNode, TransparencyAttrib
|
||||
from panda3d.core import LPoint3, LVector3
|
||||
from direct.gui.OnscreenText import OnscreenText
|
||||
from direct.task.Task import Task
|
||||
from math import sin, cos, pi
|
||||
from random import randint, choice, random
|
||||
from direct.interval.MetaInterval import Sequence
|
||||
from direct.interval.FunctionInterval import Wait, Func
|
||||
import sys
|
||||
|
||||
# Constants that will control the behavior of the game. It is good to
|
||||
# group constants like this so that they can be changed once without
|
||||
# having to find everywhere they are used in code
|
||||
SPRITE_POS = 55 # At default field of view and a depth of 55, the screen
|
||||
# dimensions is 40x30 units
|
||||
SCREEN_X = 20 # Screen goes from -20 to 20 on X
|
||||
SCREEN_Y = 15 # Screen goes from -15 to 15 on Y
|
||||
TURN_RATE = 360 # Degrees ship can turn in 1 second
|
||||
ACCELERATION = 10 # Ship acceleration in units/sec/sec
|
||||
MAX_VEL = 6 # Maximum ship velocity in units/sec
|
||||
MAX_VEL_SQ = MAX_VEL ** 2 # Square of the ship velocity
|
||||
DEG_TO_RAD = pi / 180 # translates degrees to radians for sin and cos
|
||||
BULLET_LIFE = 2 # How long bullets stay on screen before removed
|
||||
BULLET_REPEAT = .2 # How often bullets can be fired
|
||||
BULLET_SPEED = 10 # Speed bullets move
|
||||
AST_INIT_VEL = 1 # Velocity of the largest asteroids
|
||||
AST_INIT_SCALE = 3 # Initial asteroid scale
|
||||
AST_VEL_SCALE = 2.2 # How much asteroid speed multiplies when broken up
|
||||
AST_SIZE_SCALE = .6 # How much asteroid scale changes when broken up
|
||||
AST_MIN_SCALE = 1.1 # If and asteroid is smaller than this and is hit,
|
||||
# it disapears instead of splitting up
|
||||
|
||||
|
||||
# This helps reduce the amount of code used by loading objects, since all of
|
||||
# the objects are pretty much the same.
|
||||
def loadObject(tex=None, pos=LPoint3(0, 0), depth=SPRITE_POS, scale=1,
|
||||
transparency=True):
|
||||
# Every object uses the plane model and is parented to the camera
|
||||
# so that it faces the screen.
|
||||
obj = loader.loadModel("models/plane")
|
||||
obj.reparentTo(camera)
|
||||
|
||||
# Set the initial position and scale.
|
||||
obj.setPos(pos.getX(), depth, pos.getY())
|
||||
obj.setScale(scale)
|
||||
|
||||
# This tells Panda not to worry about the order that things are drawn in
|
||||
# (ie. disable Z-testing). This prevents an effect known as Z-fighting.
|
||||
obj.setBin("unsorted", 0)
|
||||
obj.setDepthTest(False)
|
||||
|
||||
if transparency:
|
||||
# Enable transparency blending.
|
||||
obj.setTransparency(TransparencyAttrib.MAlpha)
|
||||
|
||||
if tex:
|
||||
# Load and set the requested texture.
|
||||
tex = loader.loadTexture("textures/" + tex)
|
||||
obj.setTexture(tex, 1)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
# Macro-like function used to reduce the amount to code needed to create the
|
||||
# on screen instructions
|
||||
def genLabelText(text, i):
|
||||
return OnscreenText(text=text, parent=base.a2dTopLeft, pos=(0.07, -.06 * i - 0.1),
|
||||
fg=(1, 1, 1, 1), align=TextNode.ALeft, shadow=(0, 0, 0, 0.5), scale=.05)
|
||||
|
||||
|
||||
class AsteroidsDemo(ShowBase):
|
||||
|
||||
def __init__(self):
|
||||
# Initialize the ShowBase class from which we inherit, which will
|
||||
# create a window and set up everything we need for rendering into it.
|
||||
ShowBase.__init__(self)
|
||||
|
||||
# This code puts the standard title and instruction text on screen
|
||||
self.title = OnscreenText(text="Panda3D: Tutorial - Tasks",
|
||||
parent=base.a2dBottomRight, scale=.07,
|
||||
align=TextNode.ARight, pos=(-0.1, 0.1),
|
||||
fg=(1, 1, 1, 1), shadow=(0, 0, 0, 0.5))
|
||||
self.escapeText = genLabelText("ESC: Quit", 0)
|
||||
self.leftkeyText = genLabelText("[Left Arrow]: Turn Left (CCW)", 1)
|
||||
self.rightkeyText = genLabelText("[Right Arrow]: Turn Right (CW)", 2)
|
||||
self.upkeyText = genLabelText("[Up Arrow]: Accelerate", 3)
|
||||
self.spacekeyText = genLabelText("[Space Bar]: Fire", 4)
|
||||
|
||||
# Disable default mouse-based camera control. This is a method on the
|
||||
# ShowBase class from which we inherit.
|
||||
self.disableMouse()
|
||||
|
||||
# Load the background starfield.
|
||||
self.setBackgroundColor((0, 0, 0, 1))
|
||||
self.bg = loadObject("stars.jpg", scale=146, depth=200,
|
||||
transparency=False)
|
||||
|
||||
# Load the ship and set its initial velocity.
|
||||
self.ship = loadObject("ship.png")
|
||||
self.setVelocity(self.ship, LVector3.zero())
|
||||
|
||||
# A dictionary of what keys are currently being pressed
|
||||
# The key events update this list, and our task will query it as input
|
||||
self.keys = {"turnLeft": 0, "turnRight": 0,
|
||||
"accel": 0, "fire": 0}
|
||||
|
||||
self.accept("escape", sys.exit) # Escape quits
|
||||
# Other keys events set the appropriate value in our key dictionary
|
||||
self.accept("arrow_left", self.setKey, ["turnLeft", 1])
|
||||
self.accept("arrow_left-up", self.setKey, ["turnLeft", 0])
|
||||
self.accept("arrow_right", self.setKey, ["turnRight", 1])
|
||||
self.accept("arrow_right-up", self.setKey, ["turnRight", 0])
|
||||
self.accept("arrow_up", self.setKey, ["accel", 1])
|
||||
self.accept("arrow_up-up", self.setKey, ["accel", 0])
|
||||
self.accept("space", self.setKey, ["fire", 1])
|
||||
|
||||
# Now we create the task. taskMgr is the task manager that actually
|
||||
# calls the function each frame. The add method creates a new task.
|
||||
# The first argument is the function to be called, and the second
|
||||
# argument is the name for the task. It returns a task object which
|
||||
# is passed to the function each frame.
|
||||
self.gameTask = taskMgr.add(self.gameLoop, "gameLoop")
|
||||
|
||||
# Stores the time at which the next bullet may be fired.
|
||||
self.nextBullet = 0.0
|
||||
|
||||
# This list will stored fired bullets.
|
||||
self.bullets = []
|
||||
|
||||
# Complete initialization by spawning the asteroids.
|
||||
self.spawnAsteroids()
|
||||
|
||||
# As described earlier, this simply sets a key in the self.keys dictionary
|
||||
# to the given value.
|
||||
def setKey(self, key, val):
|
||||
self.keys[key] = val
|
||||
|
||||
def setVelocity(self, obj, val):
|
||||
obj.setPythonTag("velocity", val)
|
||||
|
||||
def getVelocity(self, obj):
|
||||
return obj.getPythonTag("velocity")
|
||||
|
||||
def setExpires(self, obj, val):
|
||||
obj.setPythonTag("expires", val)
|
||||
|
||||
def getExpires(self, obj):
|
||||
return obj.getPythonTag("expires")
|
||||
|
||||
def spawnAsteroids(self):
|
||||
# Control variable for if the ship is alive
|
||||
self.alive = True
|
||||
self.asteroids = [] # List that will contain our asteroids
|
||||
|
||||
for i in range(10):
|
||||
# This loads an asteroid. The texture chosen is random
|
||||
# from "asteroid1.png" to "asteroid3.png".
|
||||
asteroid = loadObject("asteroid%d.png" % (randint(1, 3)),
|
||||
scale=AST_INIT_SCALE)
|
||||
self.asteroids.append(asteroid)
|
||||
|
||||
# This is kind of a hack, but it keeps the asteroids from spawning
|
||||
# near the player. It creates the list (-20, -19 ... -5, 5, 6, 7,
|
||||
# ... 20) and chooses a value from it. Since the player starts at 0
|
||||
# and this list doesn't contain anything from -4 to 4, it won't be
|
||||
# close to the player.
|
||||
asteroid.setX(choice(range(-SCREEN_X, -5) + range(5, SCREEN_X)))
|
||||
# Same thing for Y, but from -15 to 15
|
||||
asteroid.setZ(choice(range(-SCREEN_Y, -5) + range(5, SCREEN_Y)))
|
||||
|
||||
# Heading is a random angle in radians
|
||||
heading = random() * 2 * pi
|
||||
|
||||
# Converts the heading to a vector and multiplies it by speed to
|
||||
# get a velocity vector
|
||||
v = LVector3(sin(heading), 0, cos(heading)) * AST_INIT_VEL
|
||||
self.setVelocity(self.asteroids[i], v)
|
||||
|
||||
# This is our main task function, which does all of the per-frame
|
||||
# processing. It takes in self like all functions in a class, and task,
|
||||
# the task object returned by taskMgr.
|
||||
def gameLoop(self, task):
|
||||
# Get the time elapsed since the next frame. We need this for our
|
||||
# distance and velocity calculations.
|
||||
dt = globalClock.getDt()
|
||||
|
||||
# If the ship is not alive, do nothing. Tasks return Task.cont to
|
||||
# signify that the task should continue running. If Task.done were
|
||||
# returned instead, the task would be removed and would no longer be
|
||||
# called every frame.
|
||||
if not self.alive:
|
||||
return Task.cont
|
||||
|
||||
# update ship position
|
||||
self.updateShip(dt)
|
||||
|
||||
# check to see if the ship can fire
|
||||
if self.keys["fire"] and task.time > self.nextBullet:
|
||||
self.fire(task.time) # If so, call the fire function
|
||||
# And disable firing for a bit
|
||||
self.nextBullet = task.time + BULLET_REPEAT
|
||||
# Remove the fire flag until the next spacebar press
|
||||
self.keys["fire"] = 0
|
||||
|
||||
# update asteroids
|
||||
for obj in self.asteroids:
|
||||
self.updatePos(obj, dt)
|
||||
|
||||
# update bullets
|
||||
newBulletArray = []
|
||||
for obj in self.bullets:
|
||||
self.updatePos(obj, dt) # Update the bullet
|
||||
# Bullets have an experation time (see definition of fire)
|
||||
# If a bullet has not expired, add it to the new bullet list so
|
||||
# that it will continue to exist.
|
||||
if self.getExpires(obj) > task.time:
|
||||
newBulletArray.append(obj)
|
||||
else:
|
||||
obj.removeNode() # Otherwise, remove it from the scene.
|
||||
# Set the bullet array to be the newly updated array
|
||||
self.bullets = newBulletArray
|
||||
|
||||
# Check bullet collision with asteroids
|
||||
# In short, it checks every bullet against every asteroid. This is
|
||||
# quite slow. A big optimization would be to sort the objects left to
|
||||
# right and check only if they overlap. Framerate can go way down if
|
||||
# there are many bullets on screen, but for the most part it's okay.
|
||||
for bullet in self.bullets:
|
||||
# This range statement makes it step though the asteroid list
|
||||
# backwards. This is because if an asteroid is removed, the
|
||||
# elements after it will change position in the list. If you go
|
||||
# backwards, the length stays constant.
|
||||
for i in range(len(self.asteroids) - 1, -1, -1):
|
||||
asteroid = self.asteroids[i]
|
||||
# Panda's collision detection is more complicated than we need
|
||||
# here. This is the basic sphere collision check. If the
|
||||
# distance between the object centers is less than sum of the
|
||||
# radii of the two objects, then we have a collision. We use
|
||||
# lengthSquared() since it is faster than length().
|
||||
if ((bullet.getPos() - asteroid.getPos()).lengthSquared() <
|
||||
(((bullet.getScale().getX() + asteroid.getScale().getX())
|
||||
* .5) ** 2)):
|
||||
# Schedule the bullet for removal
|
||||
self.setExpires(bullet, 0)
|
||||
self.asteroidHit(i) # Handle the hit
|
||||
|
||||
# Now we do the same collision pass for the ship
|
||||
shipSize = self.ship.getScale().getX()
|
||||
for ast in self.asteroids:
|
||||
# Same sphere collision check for the ship vs. the asteroid
|
||||
if ((self.ship.getPos() - ast.getPos()).lengthSquared() <
|
||||
(((shipSize + ast.getScale().getX()) * .5) ** 2)):
|
||||
# If there is a hit, clear the screen and schedule a restart
|
||||
self.alive = False # Ship is no longer alive
|
||||
# Remove every object in asteroids and bullets from the scene
|
||||
for i in self.asteroids + self.bullets:
|
||||
i.removeNode()
|
||||
self.bullets = [] # Clear the bullet list
|
||||
self.ship.hide() # Hide the ship
|
||||
# Reset the velocity
|
||||
self.setVelocity(self.ship, LVector3(0, 0, 0))
|
||||
Sequence(Wait(2), # Wait 2 seconds
|
||||
Func(self.ship.setR, 0), # Reset heading
|
||||
Func(self.ship.setX, 0), # Reset position X
|
||||
# Reset position Y (Z for Panda)
|
||||
Func(self.ship.setZ, 0),
|
||||
Func(self.ship.show), # Show the ship
|
||||
Func(self.spawnAsteroids)).start() # Remake asteroids
|
||||
return Task.cont
|
||||
|
||||
# If the player has successfully destroyed all asteroids, respawn them
|
||||
if len(self.asteroids) == 0:
|
||||
self.spawnAsteroids()
|
||||
|
||||
return Task.cont # Since every return is Task.cont, the task will
|
||||
# continue indefinitely
|
||||
|
||||
# Updates the positions of objects
|
||||
def updatePos(self, obj, dt):
|
||||
vel = self.getVelocity(obj)
|
||||
newPos = obj.getPos() + (vel * dt)
|
||||
|
||||
# Check if the object is out of bounds. If so, wrap it
|
||||
radius = .5 * obj.getScale().getX()
|
||||
if newPos.getX() - radius > SCREEN_X:
|
||||
newPos.setX(-SCREEN_X)
|
||||
elif newPos.getX() + radius < -SCREEN_X:
|
||||
newPos.setX(SCREEN_X)
|
||||
if newPos.getZ() - radius > SCREEN_Y:
|
||||
newPos.setZ(-SCREEN_Y)
|
||||
elif newPos.getZ() + radius < -SCREEN_Y:
|
||||
newPos.setZ(SCREEN_Y)
|
||||
|
||||
obj.setPos(newPos)
|
||||
|
||||
# The handler when an asteroid is hit by a bullet
|
||||
def asteroidHit(self, index):
|
||||
# If the asteroid is small it is simply removed
|
||||
if self.asteroids[index].getScale().getX() <= AST_MIN_SCALE:
|
||||
self.asteroids[index].removeNode()
|
||||
# Remove the asteroid from the list of asteroids.
|
||||
del self.asteroids[index]
|
||||
else:
|
||||
# If it is big enough, divide it up into little asteroids.
|
||||
# First we update the current asteroid.
|
||||
asteroid = self.asteroids[index]
|
||||
newScale = asteroid.getScale().getX() * AST_SIZE_SCALE
|
||||
asteroid.setScale(newScale) # Rescale it
|
||||
|
||||
# The new direction is chosen as perpendicular to the old direction
|
||||
# This is determined using the cross product, which returns a
|
||||
# vector perpendicular to the two input vectors. By crossing
|
||||
# velocity with a vector that goes into the screen, we get a vector
|
||||
# that is orthagonal to the original velocity in the screen plane.
|
||||
vel = self.getVelocity(asteroid)
|
||||
speed = vel.length() * AST_VEL_SCALE
|
||||
vel.normalize()
|
||||
vel = LVector3(0, 1, 0).cross(vel)
|
||||
vel *= speed
|
||||
self.setVelocity(asteroid, vel)
|
||||
|
||||
# Now we create a new asteroid identical to the current one
|
||||
newAst = loadObject(scale=newScale)
|
||||
self.setVelocity(newAst, vel * -1)
|
||||
newAst.setPos(asteroid.getPos())
|
||||
newAst.setTexture(asteroid.getTexture(), 1)
|
||||
self.asteroids.append(newAst)
|
||||
|
||||
# This updates the ship's position. This is similar to the general update
|
||||
# but takes into account turn and thrust
|
||||
def updateShip(self, dt):
|
||||
heading = self.ship.getR() # Heading is the roll value for this model
|
||||
# Change heading if left or right is being pressed
|
||||
if self.keys["turnRight"]:
|
||||
heading += dt * TURN_RATE
|
||||
self.ship.setR(heading % 360)
|
||||
elif self.keys["turnLeft"]:
|
||||
heading -= dt * TURN_RATE
|
||||
self.ship.setR(heading % 360)
|
||||
|
||||
# Thrust causes acceleration in the direction the ship is currently
|
||||
# facing
|
||||
if self.keys["accel"]:
|
||||
heading_rad = DEG_TO_RAD * heading
|
||||
# This builds a new velocity vector and adds it to the current one
|
||||
# relative to the camera, the screen in Panda is the XZ plane.
|
||||
# Therefore all of our Y values in our velocities are 0 to signify
|
||||
# no change in that direction.
|
||||
newVel = \
|
||||
LVector3(sin(heading_rad), 0, cos(heading_rad)) * ACCELERATION * dt
|
||||
newVel += self.getVelocity(self.ship)
|
||||
# Clamps the new velocity to the maximum speed. lengthSquared() is
|
||||
# used again since it is faster than length()
|
||||
if newVel.lengthSquared() > MAX_VEL_SQ:
|
||||
newVel.normalize()
|
||||
newVel *= MAX_VEL
|
||||
self.setVelocity(self.ship, newVel)
|
||||
|
||||
# Finally, update the position as with any other object
|
||||
self.updatePos(self.ship, dt)
|
||||
|
||||
# Creates a bullet and adds it to the bullet list
|
||||
def fire(self, time):
|
||||
direction = DEG_TO_RAD * self.ship.getR()
|
||||
pos = self.ship.getPos()
|
||||
bullet = loadObject("bullet.png", scale=.2) # Create the object
|
||||
bullet.setPos(pos)
|
||||
# Velocity is in relation to the ship
|
||||
vel = (self.getVelocity(self.ship) +
|
||||
(LVector3(sin(direction), 0, cos(direction)) *
|
||||
BULLET_SPEED))
|
||||
self.setVelocity(bullet, vel)
|
||||
# Set the bullet expiration time to be a certain amount past the
|
||||
# current time
|
||||
self.setExpires(bullet, time + BULLET_LIFE)
|
||||
|
||||
# Finally, add the new bullet to the list
|
||||
self.bullets.append(bullet)
|
||||
|
||||
# We now have everything we need. Make an instance of the class and start
|
||||
# 3D rendering
|
||||
demo = AsteroidsDemo()
|
||||
demo.run()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<CoordinateSystem> { Y-Up }
|
||||
|
||||
<Comment> {
|
||||
"maya2egg plane.mb plane.egg"
|
||||
}
|
||||
<Group> groundPlane_transform {
|
||||
}
|
||||
<Group> pPlane1 {
|
||||
<VertexPool> pPlaneShape1.verts {
|
||||
<Vertex> 1 {
|
||||
-0.5 -0.5 0
|
||||
<Normal> { 0 0 -1 }
|
||||
<UV> { 0 0 }
|
||||
<RGBA> { 1 1 1 1 }
|
||||
}
|
||||
<Vertex> 2 {
|
||||
-0.5 0.5 0
|
||||
<Normal> { 0 0 -1 }
|
||||
<UV> { 0 1 }
|
||||
<RGBA> { 1 1 1 1 }
|
||||
}
|
||||
<Vertex> 3 {
|
||||
0.5 -0.5 0
|
||||
<Normal> { 0 0 -1 }
|
||||
<UV> { 1 0 }
|
||||
<RGBA> { 1 1 1 1 }
|
||||
}
|
||||
<Vertex> 4 {
|
||||
0.5 0.5 0
|
||||
<Normal> { 0 0 -1 }
|
||||
<UV> { 1 1 }
|
||||
<RGBA> { 1 1 1 1 }
|
||||
}
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0 0 -1 }
|
||||
<VertexRef>{ 3 4 2 1 <Ref> { pPlaneShape1.verts } }
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 282 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
|
@ -0,0 +1,338 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Author: Shao Zhang, Phil Saltzman
|
||||
# Last Updated: 2015-03-13
|
||||
#
|
||||
# This tutorial shows how to detect and respond to collisions. It uses solids
|
||||
# create in code and the egg files, how to set up collision masks, a traverser,
|
||||
# and a handler, how to detect collisions, and how to dispatch function based
|
||||
# on the collisions. All of this is put together to simulate a labyrinth-style
|
||||
# game
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from panda3d.core import CollisionTraverser, CollisionNode
|
||||
from panda3d.core import CollisionHandlerQueue, CollisionRay
|
||||
from panda3d.core import Material, LRotationf, NodePath
|
||||
from panda3d.core import AmbientLight, DirectionalLight
|
||||
from panda3d.core import TextNode
|
||||
from panda3d.core import LVector3, BitMask32
|
||||
from direct.gui.OnscreenText import OnscreenText
|
||||
from direct.interval.MetaInterval import Sequence, Parallel
|
||||
from direct.interval.LerpInterval import LerpFunc
|
||||
from direct.interval.FunctionInterval import Func, Wait
|
||||
from direct.task.Task import Task
|
||||
import sys
|
||||
|
||||
# Some constants for the program
|
||||
ACCEL = 70 # Acceleration in ft/sec/sec
|
||||
MAX_SPEED = 5 # Max speed in ft/sec
|
||||
MAX_SPEED_SQ = MAX_SPEED ** 2 # Squared to make it easier to use lengthSquared
|
||||
# Instead of length
|
||||
|
||||
|
||||
class BallInMazeDemo(ShowBase):
|
||||
|
||||
def __init__(self):
|
||||
# Initialize the ShowBase class from which we inherit, which will
|
||||
# create a window and set up everything we need for rendering into it.
|
||||
ShowBase.__init__(self)
|
||||
|
||||
# This code puts the standard title and instruction text on screen
|
||||
self.title = \
|
||||
OnscreenText(text="Panda3D: Tutorial - Collision Detection",
|
||||
parent=base.a2dBottomRight, align=TextNode.ARight,
|
||||
fg=(1, 1, 1, 1), pos=(-0.1, 0.1), scale=.08,
|
||||
shadow=(0, 0, 0, 0.5))
|
||||
self.instructions = \
|
||||
OnscreenText(text="Mouse pointer tilts the board",
|
||||
parent=base.a2dTopLeft, align=TextNode.ALeft,
|
||||
pos=(0.05, -0.08), fg=(1, 1, 1, 1), scale=.06,
|
||||
shadow=(0, 0, 0, 0.5))
|
||||
|
||||
self.accept("escape", sys.exit) # Escape quits
|
||||
|
||||
# Disable default mouse-based camera control. This is a method on the
|
||||
# ShowBase class from which we inherit.
|
||||
self.disableMouse()
|
||||
camera.setPosHpr(0, 0, 25, 0, -90, 0) # Place the camera
|
||||
|
||||
# Load the maze and place it in the scene
|
||||
self.maze = loader.loadModel("models/maze")
|
||||
self.maze.reparentTo(render)
|
||||
|
||||
# Most times, you want collisions to be tested against invisible geometry
|
||||
# rather than every polygon. This is because testing against every polygon
|
||||
# in the scene is usually too slow. You can have simplified or approximate
|
||||
# geometry for the solids and still get good results.
|
||||
#
|
||||
# Sometimes you'll want to create and position your own collision solids in
|
||||
# code, but it's often easier to have them built automatically. This can be
|
||||
# done by adding special tags into an egg file. Check maze.egg and ball.egg
|
||||
# and look for lines starting with <Collide>. The part is brackets tells
|
||||
# Panda exactly what to do. Polyset means to use the polygons in that group
|
||||
# as solids, while Sphere tells panda to make a collision sphere around them
|
||||
# Keep means to keep the polygons in the group as visable geometry (good
|
||||
# for the ball, not for the triggers), and descend means to make sure that
|
||||
# the settings are applied to any subgroups.
|
||||
#
|
||||
# Once we have the collision tags in the models, we can get to them using
|
||||
# NodePath's find command
|
||||
|
||||
# Find the collision node named wall_collide
|
||||
self.walls = self.maze.find("**/wall_collide")
|
||||
|
||||
# Collision objects are sorted using BitMasks. BitMasks are ordinary numbers
|
||||
# with extra methods for working with them as binary bits. Every collision
|
||||
# solid has both a from mask and an into mask. Before Panda tests two
|
||||
# objects, it checks to make sure that the from and into collision masks
|
||||
# have at least one bit in common. That way things that shouldn't interact
|
||||
# won't. Normal model nodes have collision masks as well. By default they
|
||||
# are set to bit 20. If you want to collide against actual visable polygons,
|
||||
# set a from collide mask to include bit 20
|
||||
#
|
||||
# For this example, we will make everything we want the ball to collide with
|
||||
# include bit 0
|
||||
self.walls.node().setIntoCollideMask(BitMask32.bit(0))
|
||||
# CollisionNodes are usually invisible but can be shown. Uncomment the next
|
||||
# line to see the collision walls
|
||||
#self.walls.show()
|
||||
|
||||
# We will now find the triggers for the holes and set their masks to 0 as
|
||||
# well. We also set their names to make them easier to identify during
|
||||
# collisions
|
||||
self.loseTriggers = []
|
||||
for i in range(6):
|
||||
trigger = self.maze.find("**/hole_collide" + str(i))
|
||||
trigger.node().setIntoCollideMask(BitMask32.bit(0))
|
||||
trigger.node().setName("loseTrigger")
|
||||
self.loseTriggers.append(trigger)
|
||||
# Uncomment this line to see the triggers
|
||||
# trigger.show()
|
||||
|
||||
# Ground_collide is a single polygon on the same plane as the ground in the
|
||||
# maze. We will use a ray to collide with it so that we will know exactly
|
||||
# what height to put the ball at every frame. Since this is not something
|
||||
# that we want the ball itself to collide with, it has a different
|
||||
# bitmask.
|
||||
self.mazeGround = self.maze.find("**/ground_collide")
|
||||
self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1))
|
||||
|
||||
# Load the ball and attach it to the scene
|
||||
# It is on a root dummy node so that we can rotate the ball itself without
|
||||
# rotating the ray that will be attached to it
|
||||
self.ballRoot = render.attachNewNode("ballRoot")
|
||||
self.ball = loader.loadModel("models/ball")
|
||||
self.ball.reparentTo(self.ballRoot)
|
||||
|
||||
# Find the collison sphere for the ball which was created in the egg file
|
||||
# Notice that it has a from collision mask of bit 0, and an into collison
|
||||
# mask of no bits. This means that the ball can only cause collisions, not
|
||||
# be collided into
|
||||
self.ballSphere = self.ball.find("**/ball")
|
||||
self.ballSphere.node().setFromCollideMask(BitMask32.bit(0))
|
||||
self.ballSphere.node().setIntoCollideMask(BitMask32.allOff())
|
||||
|
||||
# No we create a ray to start above the ball and cast down. This is to
|
||||
# Determine the height the ball should be at and the angle the floor is
|
||||
# tilting. We could have used the sphere around the ball itself, but it
|
||||
# would not be as reliable
|
||||
self.ballGroundRay = CollisionRay() # Create the ray
|
||||
self.ballGroundRay.setOrigin(0, 0, 10) # Set its origin
|
||||
self.ballGroundRay.setDirection(0, 0, -1) # And its direction
|
||||
# Collision solids go in CollisionNode
|
||||
# Create and name the node
|
||||
self.ballGroundCol = CollisionNode('groundRay')
|
||||
self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray
|
||||
self.ballGroundCol.setFromCollideMask(
|
||||
BitMask32.bit(1)) # Set its bitmasks
|
||||
self.ballGroundCol.setIntoCollideMask(BitMask32.allOff())
|
||||
# Attach the node to the ballRoot so that the ray is relative to the ball
|
||||
# (it will always be 10 feet over the ball and point down)
|
||||
self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol)
|
||||
# Uncomment this line to see the ray
|
||||
#self.ballGroundColNp.show()
|
||||
|
||||
# Finally, we create a CollisionTraverser. CollisionTraversers are what
|
||||
# do the job of walking the scene graph and calculating collisions.
|
||||
# For a traverser to actually do collisions, you need to call
|
||||
# traverser.traverse() on a part of the scene. Fortunately, ShowBase
|
||||
# has a task that does this for the entire scene once a frame. By
|
||||
# assigning it to self.cTrav, we designate that this is the one that
|
||||
# it should call traverse() on each frame.
|
||||
self.cTrav = CollisionTraverser()
|
||||
|
||||
# Collision traversers tell collision handlers about collisions, and then
|
||||
# the handler decides what to do with the information. We are using a
|
||||
# CollisionHandlerQueue, which simply creates a list of all of the
|
||||
# collisions in a given pass. There are more sophisticated handlers like
|
||||
# one that sends events and another that tries to keep collided objects
|
||||
# apart, but the results are often better with a simple queue
|
||||
self.cHandler = CollisionHandlerQueue()
|
||||
# Now we add the collision nodes that can create a collision to the
|
||||
# traverser. The traverser will compare these to all others nodes in the
|
||||
# scene. There is a limit of 32 CollisionNodes per traverser
|
||||
# We add the collider, and the handler to use as a pair
|
||||
self.cTrav.addCollider(self.ballSphere, self.cHandler)
|
||||
self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)
|
||||
|
||||
# Collision traversers have a built in tool to help visualize collisions.
|
||||
# Uncomment the next line to see it.
|
||||
#self.cTrav.showCollisions(render)
|
||||
|
||||
# This section deals with lighting for the ball. Only the ball was lit
|
||||
# because the maze has static lighting pregenerated by the modeler
|
||||
ambientLight = AmbientLight("ambientLight")
|
||||
ambientLight.setColor((.55, .55, .55, 1))
|
||||
directionalLight = DirectionalLight("directionalLight")
|
||||
directionalLight.setDirection(LVector3(0, 0, -1))
|
||||
directionalLight.setColor((0.375, 0.375, 0.375, 1))
|
||||
directionalLight.setSpecularColor((1, 1, 1, 1))
|
||||
self.ballRoot.setLight(render.attachNewNode(ambientLight))
|
||||
self.ballRoot.setLight(render.attachNewNode(directionalLight))
|
||||
|
||||
# This section deals with adding a specular highlight to the ball to make
|
||||
# it look shiny. Normally, this is specified in the .egg file.
|
||||
m = Material()
|
||||
m.setSpecular((1, 1, 1, 1))
|
||||
m.setShininess(96)
|
||||
self.ball.setMaterial(m, 1)
|
||||
|
||||
# Finally, we call start for more initialization
|
||||
self.start()
|
||||
|
||||
def start(self):
|
||||
# The maze model also has a locator in it for where to start the ball
|
||||
# To access it we use the find command
|
||||
startPos = self.maze.find("**/start").getPos()
|
||||
# Set the ball in the starting position
|
||||
self.ballRoot.setPos(startPos)
|
||||
self.ballV = LVector3(0, 0, 0) # Initial velocity is 0
|
||||
self.accelV = LVector3(0, 0, 0) # Initial acceleration is 0
|
||||
|
||||
# Create the movement task, but first make sure it is not already
|
||||
# running
|
||||
taskMgr.remove("rollTask")
|
||||
self.mainLoop = taskMgr.add(self.rollTask, "rollTask")
|
||||
|
||||
# This function handles the collision between the ray and the ground
|
||||
# Information about the interaction is passed in colEntry
|
||||
def groundCollideHandler(self, colEntry):
|
||||
# Set the ball to the appropriate Z value for it to be exactly on the
|
||||
# ground
|
||||
newZ = colEntry.getSurfacePoint(render).getZ()
|
||||
self.ballRoot.setZ(newZ + .4)
|
||||
|
||||
# Find the acceleration direction. First the surface normal is crossed with
|
||||
# the up vector to get a vector perpendicular to the slope
|
||||
norm = colEntry.getSurfaceNormal(render)
|
||||
accelSide = norm.cross(LVector3.up())
|
||||
# Then that vector is crossed with the surface normal to get a vector that
|
||||
# points down the slope. By getting the acceleration in 3D like this rather
|
||||
# than in 2D, we reduce the amount of error per-frame, reducing jitter
|
||||
self.accelV = norm.cross(accelSide)
|
||||
|
||||
# This function handles the collision between the ball and a wall
|
||||
def wallCollideHandler(self, colEntry):
|
||||
# First we calculate some numbers we need to do a reflection
|
||||
norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the wall
|
||||
curSpeed = self.ballV.length() # The current speed
|
||||
inVec = self.ballV / curSpeed # The direction of travel
|
||||
velAngle = norm.dot(inVec) # Angle of incidance
|
||||
hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos()
|
||||
hitDir.normalize()
|
||||
# The angle between the ball and the normal
|
||||
hitAngle = norm.dot(hitDir)
|
||||
|
||||
# Ignore the collision if the ball is either moving away from the wall
|
||||
# already (so that we don't accidentally send it back into the wall)
|
||||
# and ignore it if the collision isn't dead-on (to avoid getting caught on
|
||||
# corners)
|
||||
if velAngle > 0 and hitAngle > .995:
|
||||
# Standard reflection equation
|
||||
reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec
|
||||
|
||||
# This makes the velocity half of what it was if the hit was dead-on
|
||||
# and nearly exactly what it was if this is a glancing blow
|
||||
self.ballV = reflectVec * (curSpeed * (((1 - velAngle) * .5) + .5))
|
||||
# Since we have a collision, the ball is already a little bit buried in
|
||||
# the wall. This calculates a vector needed to move it so that it is
|
||||
# exactly touching the wall
|
||||
disp = (colEntry.getSurfacePoint(render) -
|
||||
colEntry.getInteriorPoint(render))
|
||||
newPos = self.ballRoot.getPos() + disp
|
||||
self.ballRoot.setPos(newPos)
|
||||
|
||||
# This is the task that deals with making everything interactive
|
||||
def rollTask(self, task):
|
||||
# Standard technique for finding the amount of time since the last
|
||||
# frame
|
||||
dt = globalClock.getDt()
|
||||
|
||||
# If dt is large, then there has been a # hiccup that could cause the ball
|
||||
# to leave the field if this functions runs, so ignore the frame
|
||||
if dt > .2:
|
||||
return Task.cont
|
||||
|
||||
# The collision handler collects the collisions. We dispatch which function
|
||||
# to handle the collision based on the name of what was collided into
|
||||
for i in range(self.cHandler.getNumEntries()):
|
||||
entry = self.cHandler.getEntry(i)
|
||||
name = entry.getIntoNode().getName()
|
||||
if name == "wall_collide":
|
||||
self.wallCollideHandler(entry)
|
||||
elif name == "ground_collide":
|
||||
self.groundCollideHandler(entry)
|
||||
elif name == "loseTrigger":
|
||||
self.loseGame(entry)
|
||||
|
||||
# Read the mouse position and tilt the maze accordingly
|
||||
if base.mouseWatcherNode.hasMouse():
|
||||
mpos = base.mouseWatcherNode.getMouse() # get the mouse position
|
||||
self.maze.setP(mpos.getY() * -10)
|
||||
self.maze.setR(mpos.getX() * 10)
|
||||
|
||||
# Finally, we move the ball
|
||||
# Update the velocity based on acceleration
|
||||
self.ballV += self.accelV * dt * ACCEL
|
||||
# Clamp the velocity to the maximum speed
|
||||
if self.ballV.lengthSquared() > MAX_SPEED_SQ:
|
||||
self.ballV.normalize()
|
||||
self.ballV *= MAX_SPEED
|
||||
# Update the position based on the velocity
|
||||
self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV * dt))
|
||||
|
||||
# This block of code rotates the ball. It uses something called a quaternion
|
||||
# to rotate the ball around an arbitrary axis. That axis perpendicular to
|
||||
# the balls rotation, and the amount has to do with the size of the ball
|
||||
# This is multiplied on the previous rotation to incrimentally turn it.
|
||||
prevRot = LRotationf(self.ball.getQuat())
|
||||
axis = LVector3.up().cross(self.ballV)
|
||||
newRot = LRotationf(axis, 45.5 * dt * self.ballV.length())
|
||||
self.ball.setQuat(prevRot * newRot)
|
||||
|
||||
return Task.cont # Continue the task indefinitely
|
||||
|
||||
# If the ball hits a hole trigger, then it should fall in the hole.
|
||||
# This is faked rather than dealing with the actual physics of it.
|
||||
def loseGame(self, entry):
|
||||
# The triggers are set up so that the center of the ball should move to the
|
||||
# collision point to be in the hole
|
||||
toPos = entry.getInteriorPoint(render)
|
||||
taskMgr.remove('rollTask') # Stop the maze task
|
||||
|
||||
# Move the ball into the hole over a short sequence of time. Then wait a
|
||||
# second and call start to reset the game
|
||||
Sequence(
|
||||
Parallel(
|
||||
LerpFunc(self.ballRoot.setX, fromData=self.ballRoot.getX(),
|
||||
toData=toPos.getX(), duration=.1),
|
||||
LerpFunc(self.ballRoot.setY, fromData=self.ballRoot.getY(),
|
||||
toData=toPos.getY(), duration=.1),
|
||||
LerpFunc(self.ballRoot.setZ, fromData=self.ballRoot.getZ(),
|
||||
toData=self.ballRoot.getZ() - .9, duration=.2)),
|
||||
Wait(1),
|
||||
Func(self.start)).start()
|
||||
|
||||
# Finally, create an instance of our class and start 3d rendering
|
||||
demo = BallInMazeDemo()
|
||||
demo.run()
|
||||
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
|
@ -0,0 +1,199 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Author: Shao Zhang, Phil Saltzman, and Eddie Caanan
|
||||
# Last Updated: 2015-03-13
|
||||
#
|
||||
# This tutorial shows how to play animations on models aka "actors".
|
||||
# It is based on the popular game of "Rock 'em Sock 'em Robots".
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from panda3d.core import AmbientLight, DirectionalLight
|
||||
from panda3d.core import TextNode
|
||||
from panda3d.core import LVector3
|
||||
from direct.gui.OnscreenText import OnscreenText
|
||||
from direct.interval.MetaInterval import Sequence
|
||||
from direct.interval.FunctionInterval import Func, Wait
|
||||
from direct.actor import Actor
|
||||
from random import random
|
||||
import sys
|
||||
|
||||
|
||||
class BoxingRobotDemo(ShowBase):
|
||||
# Macro-like function used to reduce the amount to code needed to create the
|
||||
# on screen instructions
|
||||
|
||||
def genLabelText(self, text, i):
|
||||
return OnscreenText(text=text, parent=base.a2dTopLeft, scale=.05,
|
||||
pos=(0.1, - 0.1 -.07 * i), fg=(1, 1, 1, 1),
|
||||
align=TextNode.ALeft)
|
||||
|
||||
def __init__(self):
|
||||
# Initialize the ShowBase class from which we inherit, which will
|
||||
# create a window and set up everything we need for rendering into it.
|
||||
ShowBase.__init__(self)
|
||||
|
||||
# This code puts the standard title and instruction text on screen
|
||||
self.title = OnscreenText(text="Panda3D: Tutorial - Actors",
|
||||
parent=base.a2dBottomRight, style=1,
|
||||
fg=(0, 0, 0, 1), pos=(-0.2, 0.1),
|
||||
align=TextNode.ARight, scale=.09)
|
||||
|
||||
self.escapeEventText = self.genLabelText("ESC: Quit", 0)
|
||||
self.akeyEventText = self.genLabelText("[A]: Robot 1 Left Punch", 1)
|
||||
self.skeyEventText = self.genLabelText("[S]: Robot 1 Right Punch", 2)
|
||||
self.kkeyEventText = self.genLabelText("[K]: Robot 2 Left Punch", 3)
|
||||
self.lkeyEventText = self.genLabelText("[L]: Robot 2 Right Punch", 4)
|
||||
|
||||
# Set the camera in a fixed position
|
||||
self.disableMouse()
|
||||
camera.setPosHpr(14.5, -15.4, 14, 45, -14, 0)
|
||||
self.setBackgroundColor(0, 0, 0)
|
||||
|
||||
# Add lighting so that the objects are not drawn flat
|
||||
self.setupLights()
|
||||
|
||||
# Load the ring
|
||||
self.ring = loader.loadModel('models/ring')
|
||||
self.ring.reparentTo(render)
|
||||
|
||||
# Models that use skeletal animation are known as Actors instead of models
|
||||
# Instead of just one file, the have one file for the main model, and an
|
||||
# additional file for each playable animation.
|
||||
# They are loaded using Actor.Actor instead of loader.LoadModel.
|
||||
# The constructor takes the location of the main object as with a normal model
|
||||
# and a dictionary (A fancy python structure that is like a lookup table)
|
||||
# that contains names for animations, and paths to the appropriate
|
||||
# files
|
||||
self.robot1 = Actor.Actor('models/robot',
|
||||
{'leftPunch': 'models/robot_left_punch',
|
||||
'rightPunch': 'models/robot_right_punch',
|
||||
'headUp': 'models/robot_head_up',
|
||||
'headDown': 'models/robot_head_down'})
|
||||
|
||||
# Actors need to be positioned and parented like normal objects
|
||||
self.robot1.setPosHprScale(-1, -2.5, 4, 45, 0, 0, 1.25, 1.25, 1.25)
|
||||
self.robot1.reparentTo(render)
|
||||
|
||||
# We'll repeat the process for the second robot. The only thing that changes
|
||||
# here is the robot's color and position
|
||||
self.robot2 = Actor.Actor('models/robot',
|
||||
{'leftPunch': 'models/robot_left_punch',
|
||||
'rightPunch': 'models/robot_right_punch',
|
||||
'headUp': 'models/robot_head_up',
|
||||
'headDown': 'models/robot_head_down'})
|
||||
|
||||
# Set the properties of this robot
|
||||
self.robot2.setPosHprScale(1, 1.5, 4, 225, 0, 0, 1.25, 1.25, 1.25)
|
||||
self.robot2.setColor((.7, 0, 0, 1))
|
||||
self.robot2.reparentTo(render)
|
||||
|
||||
# Now we define how the animated models will move. Animations are played
|
||||
# through special intervals. In this case we use actor intervals in a
|
||||
# sequence to play the part of the punch animation where the arm extends,
|
||||
# call a function to check if the punch landed, and then play the part of the
|
||||
# animation where the arm retracts
|
||||
|
||||
# Punch sequence for robot 1's left arm
|
||||
self.robot1.punchLeft = Sequence(
|
||||
# Interval for the outstreched animation
|
||||
self.robot1.actorInterval('leftPunch', startFrame=1, endFrame=10),
|
||||
# Function to check if the punch was successful
|
||||
Func(self.checkPunch, 2),
|
||||
# Interval for the retract animation
|
||||
self.robot1.actorInterval('leftPunch', startFrame=11, endFrame=32))
|
||||
|
||||
# Punch sequence for robot 1's right arm
|
||||
self.robot1.punchRight = Sequence(
|
||||
self.robot1.actorInterval('rightPunch', startFrame=1, endFrame=10),
|
||||
Func(self.checkPunch, 2),
|
||||
self.robot1.actorInterval('rightPunch', startFrame=11, endFrame=32))
|
||||
|
||||
# Punch sequence for robot 2's left arm
|
||||
self.robot2.punchLeft = Sequence(
|
||||
self.robot2.actorInterval('leftPunch', startFrame=1, endFrame=10),
|
||||
Func(self.checkPunch, 1),
|
||||
self.robot2.actorInterval('leftPunch', startFrame=11, endFrame=32))
|
||||
|
||||
# Punch sequence for robot 2's right arm
|
||||
self.robot2.punchRight = Sequence(
|
||||
self.robot2.actorInterval('rightPunch', startFrame=1, endFrame=10),
|
||||
Func(self.checkPunch, 1),
|
||||
self.robot2.actorInterval('rightPunch', startFrame=11, endFrame=32))
|
||||
|
||||
# We use the same techinique to create a sequence for when a robot is knocked
|
||||
# out where the head pops up, waits a while, and then resets
|
||||
|
||||
# Head animation for robot 1
|
||||
self.robot1.resetHead = Sequence(
|
||||
# Interval for the head going up. Since no start or end frames were given,
|
||||
# the entire animation is played.
|
||||
self.robot1.actorInterval('headUp'),
|
||||
Wait(1.5),
|
||||
# The head down animation was animated a little too quickly, so this will
|
||||
# play it at 75% of it's normal speed
|
||||
self.robot1.actorInterval('headDown', playRate=.75))
|
||||
|
||||
# Head animation for robot 2
|
||||
self.robot2.resetHead = Sequence(
|
||||
self.robot2.actorInterval('headUp'),
|
||||
Wait(1.5),
|
||||
self.robot2.actorInterval('headDown', playRate=.75))
|
||||
|
||||
# Now that we have defined the motion, we can define our key input.
|
||||
# Each fist is bound to a key. When a key is pressed, self.tryPunch checks to
|
||||
# make sure that the both robots have their heads down, and if they do it
|
||||
# plays the given interval
|
||||
self.accept('escape', sys.exit)
|
||||
self.accept('a', self.tryPunch, [self.robot1.punchLeft])
|
||||
self.accept('s', self.tryPunch, [self.robot1.punchRight])
|
||||
self.accept('k', self.tryPunch, [self.robot2.punchLeft])
|
||||
self.accept('l', self.tryPunch, [self.robot2.punchRight])
|
||||
|
||||
# tryPunch will play the interval passed to it only if
|
||||
# neither robot has 'resetHead' playing (a head is up) AND
|
||||
# the punch interval passed to it is not already playing
|
||||
def tryPunch(self, interval):
|
||||
if (not self.robot1.resetHead.isPlaying() and
|
||||
not self.robot2.resetHead.isPlaying() and
|
||||
not interval.isPlaying()):
|
||||
interval.start()
|
||||
|
||||
# checkPunch will determine if a successful punch has been thrown
|
||||
def checkPunch(self, robot):
|
||||
if robot == 1:
|
||||
# punch is directed to robot 1
|
||||
# if robot 1 is playing'resetHead', do nothing
|
||||
if self.robot1.resetHead.isPlaying():
|
||||
return
|
||||
# if robot 1 is not punching...
|
||||
if (not self.robot1.punchLeft.isPlaying() and
|
||||
not self.robot1.punchRight.isPlaying()):
|
||||
# ...15% chance of successful hit
|
||||
if random() > .85:
|
||||
self.robot1.resetHead.start()
|
||||
# Otherwise, only 5% chance of sucessful hit
|
||||
elif random() > .95:
|
||||
self.robot1.resetHead.start()
|
||||
else:
|
||||
# punch is directed to robot 2, same as above
|
||||
if self.robot2.resetHead.isPlaying():
|
||||
return
|
||||
if (not self.robot2.punchLeft.isPlaying() and
|
||||
not self.robot2.punchRight.isPlaying()):
|
||||
if random() > .85:
|
||||
self.robot2.resetHead.start()
|
||||
elif random() > .95:
|
||||
self.robot2.resetHead.start()
|
||||
|
||||
# This function sets up the lighting
|
||||
def setupLights(self):
|
||||
ambientLight = AmbientLight("ambientLight")
|
||||
ambientLight.setColor((.8, .8, .75, 1))
|
||||
directionalLight = DirectionalLight("directionalLight")
|
||||
directionalLight.setDirection(LVector3(0, 0, -2.5))
|
||||
directionalLight.setColor((0.9, 0.8, 0.9, 1))
|
||||
render.setLight(render.attachNewNode(ambientLight))
|
||||
render.setLight(render.attachNewNode(directionalLight))
|
||||
|
||||
demo = BoxingRobotDemo()
|
||||
demo.run()
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Bump mapping is a way of making polygonal surfaces look
|
||||
# less flat. This sample uses normal mapping for all
|
||||
# surfaces, and also parallax mapping for the column.
|
||||
#
|
||||
# This is a tutorial to show how to do normal mapping
|
||||
# in panda3d using the Shader Generator.
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from panda3d.core import loadPrcFileData
|
||||
from panda3d.core import WindowProperties
|
||||
from panda3d.core import Filename, Shader
|
||||
from panda3d.core import AmbientLight, PointLight
|
||||
from panda3d.core import TextNode
|
||||
from panda3d.core import LPoint3, LVector3
|
||||
from direct.task.Task import Task
|
||||
from direct.actor.Actor import Actor
|
||||
from direct.gui.OnscreenText import OnscreenText
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from direct.filter.CommonFilters import *
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# Function to put instructions on the screen.
|
||||
def addInstructions(pos, msg):
|
||||
return OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), scale=.05,
|
||||
shadow=(0, 0, 0, 1), parent=base.a2dTopLeft,
|
||||
pos=(0.08, -pos - 0.04), align=TextNode.ALeft)
|
||||
|
||||
# Function to put title on the screen.
|
||||
def addTitle(text):
|
||||
return OnscreenText(text=text, style=1, fg=(1, 1, 1, 1), scale=.08,
|
||||
parent=base.a2dBottomRight, align=TextNode.ARight,
|
||||
pos=(-0.1, 0.09), shadow=(0, 0, 0, 1))
|
||||
|
||||
|
||||
class BumpMapDemo(ShowBase):
|
||||
|
||||
def __init__(self):
|
||||
# Configure the parallax mapping settings (these are just the defaults)
|
||||
loadPrcFileData("", "parallax-mapping-samples 3\n"
|
||||
"parallax-mapping-scale 0.1")
|
||||
|
||||
# Initialize the ShowBase class from which we inherit, which will
|
||||
# create a window and set up everything we need for rendering into it.
|
||||
ShowBase.__init__(self)
|
||||
|
||||
# Check video card capabilities.
|
||||
if not self.win.getGsg().getSupportsBasicShaders():
|
||||
addTitle("Bump Mapping: "
|
||||
"Video driver reports that Cg shaders are not supported.")
|
||||
return
|
||||
|
||||
# Post the instructions
|
||||
self.title = addTitle("Panda3D: Tutorial - Bump Mapping")
|
||||
self.inst1 = addInstructions(0.06, "Press ESC to exit")
|
||||
self.inst2 = addInstructions(0.12, "Move mouse to rotate camera")
|
||||
self.inst3 = addInstructions(0.18, "Left mouse button: Move forwards")
|
||||
self.inst4 = addInstructions(0.24, "Right mouse button: Move backwards")
|
||||
self.inst5 = addInstructions(0.30, "Enter: Turn bump maps Off")
|
||||
|
||||
# Load the 'abstract room' model. This is a model of an
|
||||
# empty room containing a pillar, a pyramid, and a bunch
|
||||
# of exaggeratedly bumpy textures.
|
||||
|
||||
self.room = loader.loadModel("models/abstractroom")
|
||||
self.room.reparentTo(render)
|
||||
|
||||
# Make the mouse invisible, turn off normal mouse controls
|
||||
self.disableMouse()
|
||||
props = WindowProperties()
|
||||
props.setCursorHidden(True)
|
||||
self.win.requestProperties(props)
|
||||
self.camLens.setFov(60)
|
||||
|
||||
# Set the current viewing target
|
||||
self.focus = LVector3(55, -55, 20)
|
||||
self.heading = 180
|
||||
self.pitch = 0
|
||||
self.mousex = 0
|
||||
self.mousey = 0
|
||||
self.last = 0
|
||||
self.mousebtn = [0, 0, 0]
|
||||
|
||||
# Start the camera control task:
|
||||
taskMgr.add(self.controlCamera, "camera-task")
|
||||
self.accept("escape", sys.exit, [0])
|
||||
self.accept("mouse1", self.setMouseBtn, [0, 1])
|
||||
self.accept("mouse1-up", self.setMouseBtn, [0, 0])
|
||||
self.accept("mouse2", self.setMouseBtn, [1, 1])
|
||||
self.accept("mouse2-up", self.setMouseBtn, [1, 0])
|
||||
self.accept("mouse3", self.setMouseBtn, [2, 1])
|
||||
self.accept("mouse3-up", self.setMouseBtn, [2, 0])
|
||||
self.accept("enter", self.toggleShader)
|
||||
self.accept("j", self.rotateLight, [-1])
|
||||
self.accept("k", self.rotateLight, [1])
|
||||
self.accept("arrow_left", self.rotateCam, [-1])
|
||||
self.accept("arrow_right", self.rotateCam, [1])
|
||||
|
||||
# Add a light to the scene.
|
||||
self.lightpivot = render.attachNewNode("lightpivot")
|
||||
self.lightpivot.setPos(0, 0, 25)
|
||||
self.lightpivot.hprInterval(10, LPoint3(360, 0, 0)).loop()
|
||||
plight = PointLight('plight')
|
||||
plight.setColor((1, 1, 1, 1))
|
||||
plight.setAttenuation(LVector3(0.7, 0.05, 0))
|
||||
plnp = self.lightpivot.attachNewNode(plight)
|
||||
plnp.setPos(45, 0, 0)
|
||||
self.room.setLight(plnp)
|
||||
|
||||
# Add an ambient light
|
||||
alight = AmbientLight('alight')
|
||||
alight.setColor((0.2, 0.2, 0.2, 1))
|
||||
alnp = render.attachNewNode(alight)
|
||||
self.room.setLight(alnp)
|
||||
|
||||
# Create a sphere to denote the light
|
||||
sphere = loader.loadModel("models/icosphere")
|
||||
sphere.reparentTo(plnp)
|
||||
|
||||
# Tell Panda that it should generate shaders performing per-pixel
|
||||
# lighting for the room.
|
||||
self.room.setShaderAuto()
|
||||
|
||||
self.shaderenable = 1
|
||||
|
||||
def setMouseBtn(self, btn, value):
|
||||
self.mousebtn[btn] = value
|
||||
|
||||
def rotateLight(self, offset):
|
||||
self.lightpivot.setH(self.lightpivot.getH() + offset * 20)
|
||||
|
||||
def rotateCam(self, offset):
|
||||
self.heading = self.heading - offset * 10
|
||||
|
||||
def toggleShader(self):
|
||||
self.inst5.destroy()
|
||||
if (self.shaderenable):
|
||||
self.inst5 = addInstructions(0.30, "Enter: Turn bump maps On")
|
||||
self.shaderenable = 0
|
||||
self.room.setShaderOff()
|
||||
else:
|
||||
self.inst5 = addInstructions(0.30, "Enter: Turn bump maps Off")
|
||||
self.shaderenable = 1
|
||||
self.room.setShaderAuto()
|
||||
|
||||
def controlCamera(self, task):
|
||||
# figure out how much the mouse has moved (in pixels)
|
||||
md = self.win.getPointer(0)
|
||||
x = md.getX()
|
||||
y = md.getY()
|
||||
if self.win.movePointer(0, 100, 100):
|
||||
self.heading = self.heading - (x - 100) * 0.2
|
||||
self.pitch = self.pitch - (y - 100) * 0.2
|
||||
if self.pitch < -45:
|
||||
self.pitch = -45
|
||||
if self.pitch > 45:
|
||||
self.pitch = 45
|
||||
self.camera.setHpr(self.heading, self.pitch, 0)
|
||||
dir = self.camera.getMat().getRow3(1)
|
||||
elapsed = task.time - self.last
|
||||
if self.last == 0:
|
||||
elapsed = 0
|
||||
if self.mousebtn[0]:
|
||||
self.focus = self.focus + dir * elapsed * 30
|
||||
if self.mousebtn[1] or self.mousebtn[2]:
|
||||
self.focus = self.focus - dir * elapsed * 30
|
||||
self.camera.setPos(self.focus - (dir * 5))
|
||||
if self.camera.getX() < -59.0:
|
||||
self.camera.setX(-59)
|
||||
if self.camera.getX() > 59.0:
|
||||
self.camera.setX(59)
|
||||
if self.camera.getY() < -59.0:
|
||||
self.camera.setY(-59)
|
||||
if self.camera.getY() > 59.0:
|
||||
self.camera.setY(59)
|
||||
if self.camera.getZ() < 5.0:
|
||||
self.camera.setZ(5)
|
||||
if self.camera.getZ() > 45.0:
|
||||
self.camera.setZ(45)
|
||||
self.focus = self.camera.getPos() + (dir * 5)
|
||||
self.last = task.time
|
||||
return Task.cont
|
||||
|
||||
demo = BumpMapDemo()
|
||||
demo.run()
|
||||
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
|
@ -0,0 +1,497 @@
|
|||
<CoordinateSystem> { Z-Up }
|
||||
|
||||
<Comment> {
|
||||
"egg-trans -F icosphere.egg -o icosphere.egg"
|
||||
}
|
||||
<Group> Icosphere {
|
||||
<VertexPool> Icosphere {
|
||||
<Vertex> 0 {
|
||||
0 0 -1
|
||||
<Normal> { 0 0 -1 }
|
||||
}
|
||||
<Vertex> 1 {
|
||||
0.425323 -0.309011 -0.850654
|
||||
<Normal> { 0.425306 -0.309 -0.850642 }
|
||||
}
|
||||
<Vertex> 2 {
|
||||
-0.162456 -0.499995 -0.850654
|
||||
<Normal> { -0.16245 -0.499985 -0.850642 }
|
||||
}
|
||||
<Vertex> 3 {
|
||||
0.723607 -0.525725 -0.44722
|
||||
<Normal> { 0.723594 -0.525712 -0.447188 }
|
||||
}
|
||||
<Vertex> 4 {
|
||||
0.850648 0 -0.525736
|
||||
<Normal> { 0.850642 0 -0.525712 }
|
||||
}
|
||||
<Vertex> 5 {
|
||||
-0.52573 0 -0.850652
|
||||
<Normal> { -0.525712 0 -0.850642 }
|
||||
}
|
||||
<Vertex> 6 {
|
||||
-0.162456 0.499995 -0.850654
|
||||
<Normal> { -0.16245 0.499985 -0.850642 }
|
||||
}
|
||||
<Vertex> 7 {
|
||||
0.425323 0.309011 -0.850654
|
||||
<Normal> { 0.425306 0.309 -0.850642 }
|
||||
}
|
||||
<Vertex> 8 {
|
||||
0.951058 -0.309013 0
|
||||
<Normal> { 0.951048 -0.309 0 }
|
||||
}
|
||||
<Vertex> 9 {
|
||||
-0.276388 -0.850649 -0.44722
|
||||
<Normal> { -0.276376 -0.850642 -0.447218 }
|
||||
}
|
||||
<Vertex> 10 {
|
||||
0.262869 -0.809012 -0.525738
|
||||
<Normal> { 0.262856 -0.808985 -0.525712 }
|
||||
}
|
||||
<Vertex> 11 {
|
||||
0 -1 0
|
||||
<Normal> { 0 -1 0 }
|
||||
}
|
||||
<Vertex> 12 {
|
||||
-0.894426 0 -0.447216
|
||||
<Normal> { -0.894406 0 -0.447188 }
|
||||
}
|
||||
<Vertex> 13 {
|
||||
-0.688189 -0.499997 -0.525736
|
||||
<Normal> { -0.688162 -0.499985 -0.525712 }
|
||||
}
|
||||
<Vertex> 14 {
|
||||
-0.951058 -0.309013 0
|
||||
<Normal> { -0.951048 -0.309 0 }
|
||||
}
|
||||
<Vertex> 15 {
|
||||
-0.276388 0.850649 -0.44722
|
||||
<Normal> { -0.276376 0.850642 -0.447218 }
|
||||
}
|
||||
<Vertex> 16 {
|
||||
-0.688189 0.499997 -0.525736
|
||||
<Normal> { -0.688162 0.499985 -0.525712 }
|
||||
}
|
||||
<Vertex> 17 {
|
||||
-0.587786 0.809017 0
|
||||
<Normal> { -0.587756 0.809015 0 }
|
||||
}
|
||||
<Vertex> 18 {
|
||||
0.723607 0.525725 -0.44722
|
||||
<Normal> { 0.723594 0.525712 -0.447188 }
|
||||
}
|
||||
<Vertex> 19 {
|
||||
0.262869 0.809012 -0.525738
|
||||
<Normal> { 0.262856 0.808985 -0.525712 }
|
||||
}
|
||||
<Vertex> 20 {
|
||||
0.587786 0.809017 0
|
||||
<Normal> { 0.587756 0.809015 0 }
|
||||
}
|
||||
<Vertex> 21 {
|
||||
0.587786 -0.809017 0
|
||||
<Normal> { 0.587756 -0.809015 0 }
|
||||
}
|
||||
<Vertex> 22 {
|
||||
-0.587786 -0.809017 0
|
||||
<Normal> { -0.587756 -0.809015 0 }
|
||||
}
|
||||
<Vertex> 23 {
|
||||
-0.951058 0.309013 0
|
||||
<Normal> { -0.951048 0.309 0 }
|
||||
}
|
||||
<Vertex> 24 {
|
||||
0 1 0
|
||||
<Normal> { 0 1 0 }
|
||||
}
|
||||
<Vertex> 25 {
|
||||
0.951058 0.309013 0
|
||||
<Normal> { 0.951048 0.309 0 }
|
||||
}
|
||||
<Vertex> 26 {
|
||||
0.276388 -0.850649 0.44722
|
||||
<Normal> { 0.276376 -0.850642 0.447218 }
|
||||
}
|
||||
<Vertex> 27 {
|
||||
0.688189 -0.499997 0.525736
|
||||
<Normal> { 0.688162 -0.499985 0.525712 }
|
||||
}
|
||||
<Vertex> 28 {
|
||||
0.162456 -0.499995 0.850654
|
||||
<Normal> { 0.16245 -0.499985 0.850642 }
|
||||
}
|
||||
<Vertex> 29 {
|
||||
-0.723607 -0.525725 0.44722
|
||||
<Normal> { -0.723594 -0.525712 0.447188 }
|
||||
}
|
||||
<Vertex> 30 {
|
||||
-0.262869 -0.809012 0.525738
|
||||
<Normal> { -0.262856 -0.808985 0.525712 }
|
||||
}
|
||||
<Vertex> 31 {
|
||||
-0.425323 -0.309011 0.850654
|
||||
<Normal> { -0.425306 -0.309 0.850642 }
|
||||
}
|
||||
<Vertex> 32 {
|
||||
-0.723607 0.525725 0.44722
|
||||
<Normal> { -0.723594 0.525712 0.447188 }
|
||||
}
|
||||
<Vertex> 33 {
|
||||
-0.850648 0 0.525736
|
||||
<Normal> { -0.850642 0 0.525712 }
|
||||
}
|
||||
<Vertex> 34 {
|
||||
-0.425323 0.309011 0.850654
|
||||
<Normal> { -0.425306 0.309 0.850642 }
|
||||
}
|
||||
<Vertex> 35 {
|
||||
0.276388 0.850649 0.44722
|
||||
<Normal> { 0.276376 0.850642 0.447218 }
|
||||
}
|
||||
<Vertex> 36 {
|
||||
-0.262869 0.809012 0.525738
|
||||
<Normal> { -0.262856 0.808985 0.525712 }
|
||||
}
|
||||
<Vertex> 37 {
|
||||
0.162456 0.499995 0.850654
|
||||
<Normal> { 0.16245 0.499985 0.850642 }
|
||||
}
|
||||
<Vertex> 38 {
|
||||
0.894426 0 0.447216
|
||||
<Normal> { 0.894406 0 0.447188 }
|
||||
}
|
||||
<Vertex> 39 {
|
||||
0.688189 0.499997 0.525736
|
||||
<Normal> { 0.688162 0.499985 0.525712 }
|
||||
}
|
||||
<Vertex> 40 {
|
||||
0.52573 0 0.850652
|
||||
<Normal> { 0.525712 0 0.850642 }
|
||||
}
|
||||
<Vertex> 41 {
|
||||
0 0 1
|
||||
<Normal> { 0 0 1 }
|
||||
}
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.102381 -0.31509 -0.943523 }
|
||||
<VertexRef> { 0 1 2 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.700224 -0.268032 -0.661699 }
|
||||
<VertexRef> { 3 1 4 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.268034 -0.194736 -0.943523 }
|
||||
<VertexRef> { 0 2 5 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.268034 0.194737 -0.943523 }
|
||||
<VertexRef> { 0 5 6 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.102381 0.31509 -0.943523 }
|
||||
<VertexRef> { 0 6 7 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.904989 -0.268032 -0.330385 }
|
||||
<VertexRef> { 3 4 8 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.024747 -0.943521 -0.330386 }
|
||||
<VertexRef> { 9 10 11 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.889697 -0.315095 -0.330385 }
|
||||
<VertexRef> { 12 13 14 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.574602 0.748784 -0.330388 }
|
||||
<VertexRef> { 15 16 17 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.534576 0.777865 -0.330387 }
|
||||
<VertexRef> { 18 19 20 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.802609 -0.583126 -0.125627 }
|
||||
<VertexRef> { 3 8 21 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.306569 -0.943522 -0.125629 }
|
||||
<VertexRef> { 9 11 22 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.992077 0 -0.125628 }
|
||||
<VertexRef> { 12 14 23 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.306569 0.943522 -0.125629 }
|
||||
<VertexRef> { 15 17 24 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.802609 0.583126 -0.125627 }
|
||||
<VertexRef> { 18 20 25 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.408946 -0.628425 0.661698 }
|
||||
<VertexRef> { 26 27 28 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.4713 -0.583122 0.661699 }
|
||||
<VertexRef> { 29 30 31 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.700224 0.268032 0.661699 }
|
||||
<VertexRef> { 32 33 34 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.03853 0.748779 0.661699 }
|
||||
<VertexRef> { 35 36 37 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.724042 0.194736 0.661695 }
|
||||
<VertexRef> { 38 39 40 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.268034 0.194737 0.943523 }
|
||||
<VertexRef> { 40 37 41 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.491119 0.356821 0.794657 }
|
||||
<VertexRef> { 40 39 37 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.408946 0.628425 0.661699 }
|
||||
<VertexRef> { 39 35 37 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.102381 0.31509 0.943523 }
|
||||
<VertexRef> { 37 34 41 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.187594 0.577345 0.794658 }
|
||||
<VertexRef> { 37 36 34 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.4713 0.583122 0.661699 }
|
||||
<VertexRef> { 36 32 34 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.331305 0 0.943524 }
|
||||
<VertexRef> { 34 31 41 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.60706 0 0.794656 }
|
||||
<VertexRef> { 34 33 31 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.700224 -0.268032 0.661699 }
|
||||
<VertexRef> { 33 29 31 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.102381 -0.31509 0.943523 }
|
||||
<VertexRef> { 31 28 41 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.187594 -0.577345 0.794658 }
|
||||
<VertexRef> { 31 30 28 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.03853 -0.748779 0.661699 }
|
||||
<VertexRef> { 30 26 28 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.268034 -0.194737 0.943523 }
|
||||
<VertexRef> { 28 40 41 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.491119 -0.356821 0.794657 }
|
||||
<VertexRef> { 28 27 40 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.724042 -0.194736 0.661695 }
|
||||
<VertexRef> { 27 38 40 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.889697 0.315095 0.330385 }
|
||||
<VertexRef> { 25 39 38 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.794656 0.577348 0.187595 }
|
||||
<VertexRef> { 25 20 39 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.574602 0.748784 0.330388 }
|
||||
<VertexRef> { 20 35 39 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.024747 0.943521 0.330386 }
|
||||
<VertexRef> { 24 36 35 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.303531 0.934171 0.187597 }
|
||||
<VertexRef> { 24 17 36 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.534576 0.777865 0.330387 }
|
||||
<VertexRef> { 17 32 36 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.904989 0.268032 0.330385 }
|
||||
<VertexRef> { 23 33 32 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.982246 0 0.187599 }
|
||||
<VertexRef> { 23 14 33 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.904989 -0.268031 0.330385 }
|
||||
<VertexRef> { 14 29 33 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.534576 -0.777865 0.330387 }
|
||||
<VertexRef> { 22 30 29 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.303531 -0.934171 0.187597 }
|
||||
<VertexRef> { 22 11 30 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.024747 -0.943521 0.330386 }
|
||||
<VertexRef> { 11 26 30 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.574602 -0.748784 0.330388 }
|
||||
<VertexRef> { 21 27 26 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.794656 -0.577348 0.187595 }
|
||||
<VertexRef> { 21 8 27 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.889697 -0.315095 0.330385 }
|
||||
<VertexRef> { 8 38 27 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.306569 0.943522 0.125629 }
|
||||
<VertexRef> { 20 24 35 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.303531 0.934171 -0.187597 }
|
||||
<VertexRef> { 20 19 24 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.024747 0.943521 -0.330386 }
|
||||
<VertexRef> { 19 15 24 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.802609 0.583126 0.125627 }
|
||||
<VertexRef> { 17 23 32 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.794656 0.577348 -0.187595 }
|
||||
<VertexRef> { 17 16 23 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.889697 0.315095 -0.330385 }
|
||||
<VertexRef> { 16 12 23 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.802609 -0.583126 0.125627 }
|
||||
<VertexRef> { 14 22 29 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.794656 -0.577348 -0.187595 }
|
||||
<VertexRef> { 14 13 22 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.574602 -0.748784 -0.330388 }
|
||||
<VertexRef> { 13 9 22 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.306569 -0.943522 0.125629 }
|
||||
<VertexRef> { 11 21 26 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.303531 -0.934171 -0.187597 }
|
||||
<VertexRef> { 11 10 21 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.534576 -0.777865 -0.330387 }
|
||||
<VertexRef> { 10 3 21 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.992077 0 0.125628 }
|
||||
<VertexRef> { 8 25 38 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.982246 0 -0.187599 }
|
||||
<VertexRef> { 8 4 25 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.904989 0.268031 -0.330385 }
|
||||
<VertexRef> { 4 18 25 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.4713 0.583122 -0.661699 }
|
||||
<VertexRef> { 7 19 18 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.187594 0.577345 -0.794658 }
|
||||
<VertexRef> { 7 6 19 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.03853 0.748779 -0.661699 }
|
||||
<VertexRef> { 6 15 19 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.408946 0.628425 -0.661698 }
|
||||
<VertexRef> { 6 16 15 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.491119 0.356821 -0.794657 }
|
||||
<VertexRef> { 6 5 16 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.724042 0.194736 -0.661695 }
|
||||
<VertexRef> { 5 12 16 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.724042 -0.194736 -0.661695 }
|
||||
<VertexRef> { 5 13 12 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.491119 -0.356821 -0.794657 }
|
||||
<VertexRef> { 5 2 13 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.408946 -0.628425 -0.661698 }
|
||||
<VertexRef> { 2 9 13 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.700224 0.268032 -0.661699 }
|
||||
<VertexRef> { 4 7 18 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.60706 0 -0.794656 }
|
||||
<VertexRef> { 4 1 7 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.331305 0 -0.943524 }
|
||||
<VertexRef> { 1 0 7 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { -0.03853 -0.748779 -0.661699 }
|
||||
<VertexRef> { 2 10 9 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.187594 -0.577345 -0.794658 }
|
||||
<VertexRef> { 2 1 10 <Ref> { Icosphere } }
|
||||
}
|
||||
<Polygon> {
|
||||
<Normal> { 0.4713 -0.583122 -0.661699 }
|
||||
<VertexRef> { 1 3 10 <Ref> { Icosphere } }
|
||||
}
|
||||
}
|
||||