Merge branch 'master' into interrogate-overhaul

Conflicts:
	dtool/src/cppparser/cppBison.yxx
	dtool/src/interrogate/interfaceMakerPythonNative.cxx
This commit is contained in:
rdb 2015-03-14 16:47:31 +01:00
commit e608fa69c7
264 changed files with 15130 additions and 620 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/built_x64
/built
/samples
/thirdparty

View File

@ -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:{

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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];

View File

@ -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);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

View File

@ -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));
}

View File

@ -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();
};

View File

@ -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;

View File

@ -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();
};

View File

@ -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;

View File

@ -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();
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();

View File

@ -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");

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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();
};

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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'] = (' ', ' ')

View File

@ -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

View File

@ -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) {

View File

@ -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')

View File

@ -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);

View File

@ -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);
}

View File

@ -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."));

View File

@ -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;

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -37,9 +37,9 @@ void FrameBufferProperties::
operator = (const FrameBufferProperties &copy) {
_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;
}
////////////////////////////////////////////////////////////////////

View File

@ -67,7 +67,7 @@ private:
};
int _property[FBP_COUNT];
bool _specified[FBP_COUNT];
int _specified;
int _flags;
int _flags_specified;

View File

@ -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.
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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";
}
}

View File

@ -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

View File

@ -52,7 +52,6 @@ public:
private:
CGprogram _cg_program;
bool _glsl_profile;
pvector<CGparameter> _cg_parameter_map;

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}
}

View File

@ -11,6 +11,8 @@
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
INLINE void OdeRayGeom::
set_length(dReal length) {
dGeomRaySetLength(_id, length);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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
}

View File

@ -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__

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,5 @@
#include "config_pnmimage.cxx"
#include "convert_srgb.cxx"
#include "pfmFile.cxx"
#include "pnm-image-filter.cxx"
#include "pnmbitio.cxx"

View File

@ -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;

View File

@ -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]))

View File

@ -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);

View File

@ -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

View File

@ -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;
};

View File

@ -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 ||

View File

@ -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

399
samples/asteroids/main.py Executable file
View File

@ -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()

View File

@ -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 } }
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

338
samples/ball-in-maze/main.py Executable file
View File

@ -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()

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

199
samples/boxing-robots/main.py Executable file
View File

@ -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()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

188
samples/bump-mapping/main.py Executable file
View File

@ -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()

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View File

@ -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 } }
}
}

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