mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
pgraph nodepath fixes, pstats, invalid transforms
This commit is contained in:
parent
eda5a0383a
commit
33c59b176b
@ -24,6 +24,13 @@
|
||||
#include "cullResult.h"
|
||||
#include "qpcullTraverser.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "pStatClient.h"
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector GraphicsEngine::_cull_pcollector("Cull");
|
||||
PStatCollector GraphicsEngine::_draw_pcollector("Draw");
|
||||
#endif // CPPPARSER
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::Constructor
|
||||
@ -89,6 +96,7 @@ render_frame() {
|
||||
// **** This doesn't belong here; it really belongs in the Pipeline,
|
||||
// but here it is for now.
|
||||
ClockObject::get_global_clock()->tick();
|
||||
PStatClient::main_tick();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -199,6 +207,9 @@ cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
|
||||
void GraphicsEngine::
|
||||
do_cull(CullHandler *cull_handler, const qpNodePath &camera,
|
||||
GraphicsStateGuardian *gsg) {
|
||||
// Statistics
|
||||
PStatTimer timer(_cull_pcollector);
|
||||
|
||||
if (camera.is_empty()) {
|
||||
// No camera, no draw.
|
||||
return;
|
||||
@ -227,12 +238,12 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
|
||||
qpCullTraverser trav;
|
||||
trav.set_cull_handler(cull_handler);
|
||||
|
||||
// We will need both the camera transform (the net transform from
|
||||
// the scene to the camera) and the world transform (the camera
|
||||
// transform inverse, or the net transform from the camera to the
|
||||
// scene).
|
||||
CPT(TransformState) camera_transform = scene.get_transform(camera);
|
||||
CPT(TransformState) world_transform = camera.get_transform(scene);
|
||||
// We will need both the camera transform (the net transform to the
|
||||
// camera from the scene) and the world transform (the camera
|
||||
// transform inverse, or the net transform to the scene from the
|
||||
// camera).
|
||||
CPT(TransformState) camera_transform = camera.get_transform(scene);
|
||||
CPT(TransformState) world_transform = scene.get_transform(camera);
|
||||
|
||||
// The render transform is the same as the world transform, except
|
||||
// it is converted into the GSG's internal coordinate system. This
|
||||
@ -247,7 +258,7 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
|
||||
render_transform = cs_transform->compose(render_transform);
|
||||
}
|
||||
|
||||
trav.set_camera_transform(scene.get_transform(camera));
|
||||
trav.set_camera_transform(camera_transform);
|
||||
trav.set_render_transform(render_transform);
|
||||
|
||||
if (qpview_frustum_cull) {
|
||||
@ -281,6 +292,9 @@ do_cull(CullHandler *cull_handler, const qpNodePath &camera,
|
||||
void GraphicsEngine::
|
||||
do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
|
||||
DisplayRegion *dr) {
|
||||
// Statistics
|
||||
PStatTimer timer(_draw_pcollector);
|
||||
|
||||
if (set_gsg_lens(gsg, dr)) {
|
||||
DisplayRegionStack old_dr = gsg->push_display_region(dr);
|
||||
gsg->prepare_display_region();
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "graphicsWindow.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pset.h"
|
||||
#include "pStatCollector.h"
|
||||
|
||||
class Pipeline;
|
||||
class DisplayRegion;
|
||||
@ -68,6 +69,9 @@ private:
|
||||
|
||||
typedef pset<PT(GraphicsWindow)> Windows;
|
||||
Windows _windows;
|
||||
|
||||
static PStatCollector _cull_pcollector;
|
||||
static PStatCollector _draw_pcollector;
|
||||
};
|
||||
|
||||
#include "graphicsEngine.I"
|
||||
|
@ -383,6 +383,9 @@ add_child(PandaNode *child_node, int sort) {
|
||||
}
|
||||
|
||||
child_node->fix_chain_lengths();
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
force_bound_stale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -430,6 +433,9 @@ remove_child(int n) {
|
||||
}
|
||||
|
||||
child_node->fix_chain_lengths();
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
force_bound_stale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -476,6 +482,9 @@ remove_child(PandaNode *child_node) {
|
||||
|
||||
child_node->fix_chain_lengths();
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
force_bound_stale();
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
|
||||
// Now, look for and remove the child node from our down list.
|
||||
@ -529,6 +538,9 @@ remove_all_children() {
|
||||
|
||||
child_node->fix_chain_lengths();
|
||||
}
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
force_bound_stale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -732,6 +744,9 @@ detach(qpNodePathComponent *child) {
|
||||
|
||||
child_node->fix_chain_lengths();
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
parent_node->force_bound_stale();
|
||||
|
||||
// Now look for the child and break the actual connection.
|
||||
|
||||
// First, look for and remove the parent node from the child's up
|
||||
@ -785,6 +800,9 @@ reparent(qpNodePathComponent *new_parent, qpNodePathComponent *child, int sort)
|
||||
|
||||
cdata_child->_chains.insert(child);
|
||||
child_node->fix_chain_lengths();
|
||||
|
||||
// Mark the bounding volumes stale.
|
||||
parent_node->force_bound_stale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -706,18 +706,6 @@ set_pos(const qpNodePath &other, float x, float y, float z) {
|
||||
set_pos(other, LPoint3f(x, y, z));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::get_pos
|
||||
// Access: Published
|
||||
// Description: Returns the relative position of the referenced node
|
||||
// as seen from the other node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LPoint3f qpNodePath::
|
||||
get_pos(const qpNodePath &other) const {
|
||||
LMatrix4f mat = get_mat(other);
|
||||
return mat.get_row3(3);
|
||||
}
|
||||
|
||||
INLINE float qpNodePath::
|
||||
get_x(const qpNodePath &other) const {
|
||||
return get_pos(other)[0];
|
||||
|
@ -322,17 +322,17 @@ set_state(const qpNodePath &other, const RenderState *state) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::get_transform
|
||||
// Access: Published
|
||||
// Description: Returns the relative transform from this node to the
|
||||
// other node; i.e. the transformation of the other node
|
||||
// as seen from this node.
|
||||
// Description: Returns the relative transform to this node from the
|
||||
// other node; i.e. the transformation of this node
|
||||
// as seen from the other node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) qpNodePath::
|
||||
get_transform(const qpNodePath &other) const {
|
||||
if (is_empty()) {
|
||||
return other.get_net_transform();
|
||||
}
|
||||
if (other.is_empty()) {
|
||||
return get_net_transform()->invert_compose(TransformState::make_identity());
|
||||
return get_net_transform();
|
||||
}
|
||||
if (is_empty()) {
|
||||
return other.get_net_transform()->invert_compose(TransformState::make_identity());
|
||||
}
|
||||
|
||||
nassertr(verify_complete(), TransformState::make_identity());
|
||||
@ -343,7 +343,7 @@ get_transform(const qpNodePath &other) const {
|
||||
|
||||
CPT(TransformState) a_transform = r_get_partial_transform(_head, a_count);
|
||||
CPT(TransformState) b_transform = r_get_partial_transform(other._head, b_count);
|
||||
return a_transform->invert_compose(b_transform);
|
||||
return b_transform->invert_compose(a_transform);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -351,8 +351,8 @@ get_transform(const qpNodePath &other) const {
|
||||
// Access: Published
|
||||
// Description: Sets the transform object on this node, relative to
|
||||
// the other node. This computes a new transform object
|
||||
// that has the indicated value when seen relative to
|
||||
// the other node.
|
||||
// that will have the indicated value when seen from the
|
||||
// other node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpNodePath::
|
||||
set_transform(const qpNodePath &other, const TransformState *transform) const {
|
||||
@ -361,7 +361,7 @@ set_transform(const qpNodePath &other, const TransformState *transform) const {
|
||||
|
||||
// First, we perform a wrt to the parent, to get the conversion.
|
||||
qpNodePath parent = get_parent();
|
||||
CPT(TransformState) rel_trans = parent.get_transform(other);
|
||||
CPT(TransformState) rel_trans = other.get_transform(parent);
|
||||
|
||||
CPT(TransformState) new_trans = rel_trans->compose(transform);
|
||||
set_transform(new_trans);
|
||||
@ -491,11 +491,11 @@ get_hpr(float roll) const {
|
||||
// leaving translation and rotation untouched.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpNodePath::
|
||||
set_scale(const LVecBase3f &sv3) {
|
||||
set_scale(const LVecBase3f &scale) {
|
||||
nassertv(!is_empty());
|
||||
CPT(TransformState) transform = get_transform();
|
||||
nassertv(transform->has_components());
|
||||
set_transform(transform->set_scale(sv3));
|
||||
set_transform(transform->set_scale(scale));
|
||||
}
|
||||
|
||||
void qpNodePath::
|
||||
@ -794,6 +794,18 @@ set_z(const qpNodePath &other, float z) {
|
||||
set_pos(other, pos);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::get_pos
|
||||
// Access: Published
|
||||
// Description: Returns the relative position of the referenced node
|
||||
// as seen from the other node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f qpNodePath::
|
||||
get_pos(const qpNodePath &other) const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
return get_transform(other)->get_pos();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::set_hpr
|
||||
// Access: Published
|
||||
@ -2254,7 +2266,7 @@ r_output(ostream &out, qpNodePathComponent *comp) const {
|
||||
} else {
|
||||
out << "+" << node->get_type();
|
||||
}
|
||||
out << "[" << comp->get_length() << "]";
|
||||
// out << "[" << comp->get_length() << "]";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -168,7 +168,7 @@ PUBLISHED:
|
||||
|
||||
INLINE void set_scale(float scale);
|
||||
INLINE void set_scale(float sx, float sy, float sz);
|
||||
void set_scale(const LVecBase3f &sv3);
|
||||
void set_scale(const LVecBase3f &scale);
|
||||
void set_sx(float sx);
|
||||
void set_sy(float sy);
|
||||
void set_sz(float sz);
|
||||
@ -232,7 +232,7 @@ PUBLISHED:
|
||||
void set_x(const qpNodePath &other, float x);
|
||||
void set_y(const qpNodePath &other, float y);
|
||||
void set_z(const qpNodePath &other, float z);
|
||||
INLINE LPoint3f get_pos(const qpNodePath &other) const;
|
||||
LPoint3f get_pos(const qpNodePath &other) const;
|
||||
INLINE float get_x(const qpNodePath &other) const;
|
||||
INLINE float get_y(const qpNodePath &other) const;
|
||||
INLINE float get_z(const qpNodePath &other) const;
|
||||
|
@ -92,6 +92,18 @@ is_identity() const {
|
||||
return ((_flags & F_is_identity) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::is_invalid
|
||||
// Access: Published
|
||||
// Description: Returns true if the transform represents an invalid
|
||||
// matrix, for instance the result of inverting a
|
||||
// singular matrix, or false if the transform is valid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TransformState::
|
||||
is_invalid() const {
|
||||
return ((_flags & F_is_invalid) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::is_singular
|
||||
// Access: Published
|
||||
@ -119,8 +131,10 @@ is_singular() const {
|
||||
// that was constructed with a 4x4 may return true here
|
||||
// if the matrix is a simple affine matrix with no skew.
|
||||
//
|
||||
// If this returns true, you may safely call get_pos(),
|
||||
// etc., to retrieve the components.
|
||||
// If this returns true, you may safely call get_hpr()
|
||||
// and get_scale() to retrieve the components. (You
|
||||
// may always safely call get_pos() whether this returns
|
||||
// true or false.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TransformState::
|
||||
has_components() const {
|
||||
@ -128,16 +142,32 @@ has_components() const {
|
||||
return ((_flags & F_has_components) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::components_given
|
||||
// Access: Published
|
||||
// Description: Returns true if the transform was specified
|
||||
// componentwise, or false if it was specified with a
|
||||
// general 4x4 matrix. If this is true, the components
|
||||
// returned by get_pos(), get_hpr(), and get_scale()
|
||||
// will be exactly those that were set; otherwise, these
|
||||
// functions will return computed values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TransformState::
|
||||
components_given() const {
|
||||
return ((_flags & F_components_given) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::has_pos
|
||||
// Access: Published
|
||||
// Description: Returns true if the transform's pos component can be
|
||||
// extracted out separately. This is generally always
|
||||
// true.
|
||||
// true, unless the transform is invalid
|
||||
// (i.e. is_invalid() returns true).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TransformState::
|
||||
has_pos() const {
|
||||
return true;
|
||||
return !is_invalid();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -165,6 +195,18 @@ has_scale() const {
|
||||
return has_components();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::has_mat
|
||||
// Access: Published
|
||||
// Description: Returns true if the transform can be described as a
|
||||
// matrix. This is generally always true, unless
|
||||
// is_invalid() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TransformState::
|
||||
has_mat() const {
|
||||
return !is_invalid();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::get_pos
|
||||
// Access: Published
|
||||
@ -174,6 +216,7 @@ has_scale() const {
|
||||
INLINE const LVecBase3f &TransformState::
|
||||
get_pos() const {
|
||||
check_components();
|
||||
nassertr(has_pos(), _pos);
|
||||
return _pos;
|
||||
}
|
||||
|
||||
@ -212,6 +255,7 @@ get_scale() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4f &TransformState::
|
||||
get_mat() const {
|
||||
nassertr(has_mat(), LMatrix4f::ident_mat());
|
||||
check_mat();
|
||||
return _mat;
|
||||
}
|
||||
|
@ -154,12 +154,22 @@ TransformState::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TransformState::
|
||||
operator < (const TransformState &other) const {
|
||||
bool components_given = (_flags & F_components_given) != 0;
|
||||
bool other_components_given = (other._flags & F_components_given) != 0;
|
||||
if (components_given != other_components_given) {
|
||||
return components_given < other_components_given;
|
||||
static const int significant_flags =
|
||||
(F_is_invalid | F_is_identity | F_components_given);
|
||||
|
||||
int flags = (_flags & significant_flags);
|
||||
int other_flags = (other._flags & significant_flags);
|
||||
if (flags != other_flags) {
|
||||
return flags < other_flags;
|
||||
}
|
||||
if (components_given) {
|
||||
|
||||
if ((_flags & (F_is_invalid | F_is_identity)) != 0) {
|
||||
// All invalid transforms are equivalent to each other, and all
|
||||
// identity transforms are equivalent to each other.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((_flags & F_components_given) != 0) {
|
||||
// If the transform was specified componentwise, compare them
|
||||
// componentwise.
|
||||
int c = _pos.compare_to(other._pos);
|
||||
@ -195,6 +205,19 @@ make_identity() {
|
||||
return _identity_state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::make_invalid
|
||||
// Access: Published, Static
|
||||
// Description: Constructs an invalid transform; for instance, the
|
||||
// result of inverting a singular matrix.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TransformState::
|
||||
make_invalid() {
|
||||
TransformState *state = new TransformState;
|
||||
state->_flags = F_is_invalid | F_singular_known | F_is_singular | F_components_known | F_mat_known;
|
||||
return return_new(state);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::make_pos_hpr_scale
|
||||
// Access: Published, Static
|
||||
@ -211,12 +234,12 @@ make_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
|
||||
return make_identity();
|
||||
}
|
||||
|
||||
TransformState *attrib = new TransformState;
|
||||
attrib->_pos = pos;
|
||||
attrib->_hpr = hpr;
|
||||
attrib->_scale = scale;
|
||||
attrib->_flags = F_components_given | F_components_known | F_has_components;
|
||||
return return_new(attrib);
|
||||
TransformState *state = new TransformState;
|
||||
state->_pos = pos;
|
||||
state->_hpr = hpr;
|
||||
state->_scale = scale;
|
||||
state->_flags = F_components_given | F_components_known | F_has_components;
|
||||
return return_new(state);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -232,10 +255,10 @@ make_mat(const LMatrix4f &mat) {
|
||||
return make_identity();
|
||||
}
|
||||
|
||||
TransformState *attrib = new TransformState;
|
||||
attrib->_mat = mat;
|
||||
attrib->_flags = F_mat_known;
|
||||
return return_new(attrib);
|
||||
TransformState *state = new TransformState;
|
||||
state->_mat = mat;
|
||||
state->_flags = F_mat_known;
|
||||
return return_new(state);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -283,7 +306,7 @@ set_hpr(const LVecBase3f &hpr) const {
|
||||
CPT(TransformState) TransformState::
|
||||
set_scale(const LVecBase3f &scale) const {
|
||||
nassertr(has_components(), this);
|
||||
return make_pos_hpr_scale(get_pos(), get_scale(), get_hpr());
|
||||
return make_pos_hpr_scale(get_pos(), get_hpr(), scale);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -313,6 +336,14 @@ compose(const TransformState *other) const {
|
||||
return this;
|
||||
}
|
||||
|
||||
// If either transform is invalid, the result is invalid.
|
||||
if (is_invalid()) {
|
||||
return this;
|
||||
}
|
||||
if (other->is_invalid()) {
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other == this) {
|
||||
// compose(this) has to be handled as a special case, because the
|
||||
// caching problem is so different.
|
||||
@ -389,6 +420,14 @@ invert_compose(const TransformState *other) const {
|
||||
// Unlike compose(), the case of other->is_identity() is not quite as
|
||||
// trivial for invert_compose().
|
||||
|
||||
// If either transform is invalid, the result is invalid.
|
||||
if (is_invalid()) {
|
||||
return this;
|
||||
}
|
||||
if (other->is_invalid()) {
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other == this) {
|
||||
// a->invert_compose(a) always produces identity.
|
||||
return make_identity();
|
||||
@ -432,10 +471,18 @@ invert_compose(const TransformState *other) const {
|
||||
void TransformState::
|
||||
output(ostream &out) const {
|
||||
out << "T:";
|
||||
if (is_identity()) {
|
||||
if (is_invalid()) {
|
||||
out << "(invalid)";
|
||||
|
||||
} else if (is_identity()) {
|
||||
out << "(identity)";
|
||||
|
||||
} else if (has_components()) {
|
||||
if (components_given()) {
|
||||
out << "c";
|
||||
} else {
|
||||
out << "m";
|
||||
}
|
||||
char lead = '(';
|
||||
if (!get_pos().almost_equal(LVecBase3f(0.0f, 0.0f, 0.0f))) {
|
||||
out << lead << "pos " << get_pos();
|
||||
@ -477,11 +524,11 @@ write(ostream &out, int indent_level) const {
|
||||
// Description: This function is used to share a common TransformState
|
||||
// pointer for all equivalent TransformState objects.
|
||||
//
|
||||
// See the similar logic in RenderAttrib. The idea is
|
||||
// to create a new TransformState object and pass it
|
||||
// See the similar logic in RenderState. The idea is to
|
||||
// create a new TransformState object and pass it
|
||||
// through this function, which will share the pointer
|
||||
// with a previously-created TransformState object if it is
|
||||
// equivalent.
|
||||
// with a previously-created TransformState object if it
|
||||
// is equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TransformState::
|
||||
return_new(TransformState *state) {
|
||||
@ -517,6 +564,12 @@ return_new(TransformState *state) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TransformState::
|
||||
do_compose(const TransformState *other) const {
|
||||
nassertr((_flags & F_is_invalid) == 0, this);
|
||||
nassertr((other->_flags & F_is_invalid) == 0, other);
|
||||
|
||||
// We should do this operation componentwise if both transforms were
|
||||
// given componentwise.
|
||||
|
||||
LMatrix4f new_mat = other->get_mat() * get_mat();
|
||||
return make_mat(new_mat);
|
||||
}
|
||||
@ -528,11 +581,20 @@ do_compose(const TransformState *other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TransformState::
|
||||
do_invert_compose(const TransformState *other) const {
|
||||
// Perhaps we should cache the inverse matrix operation separately,
|
||||
// as a further optimization.
|
||||
nassertr((_flags & F_is_invalid) == 0, this);
|
||||
nassertr((other->_flags & F_is_invalid) == 0, other);
|
||||
|
||||
// We should do this operation componentwise if both transforms were
|
||||
// given componentwise.
|
||||
|
||||
// Perhaps we should cache the result of the inverse matrix
|
||||
// operation separately, as a further optimization.
|
||||
|
||||
LMatrix4f new_mat;
|
||||
new_mat.invert_from(get_mat());
|
||||
bool invertible = new_mat.invert_from(get_mat());
|
||||
if (!invertible) {
|
||||
return make_invalid();
|
||||
}
|
||||
new_mat = other->get_mat() * new_mat;
|
||||
return make_mat(new_mat);
|
||||
}
|
||||
@ -545,6 +607,7 @@ do_invert_compose(const TransformState *other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TransformState::
|
||||
calc_singular() {
|
||||
nassertv((_flags & F_is_invalid) == 0);
|
||||
bool singular = false;
|
||||
|
||||
if (has_components()) {
|
||||
@ -569,6 +632,7 @@ calc_singular() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TransformState::
|
||||
calc_components() {
|
||||
nassertv((_flags & F_is_invalid) == 0);
|
||||
if ((_flags & F_is_identity) != 0) {
|
||||
_scale.set(1.0f, 1.0f, 1.0f);
|
||||
_hpr.set(0.0f, 0.0f, 0.0f);
|
||||
@ -601,6 +665,7 @@ calc_components() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TransformState::
|
||||
calc_mat() {
|
||||
nassertv((_flags & F_is_invalid) == 0);
|
||||
if ((_flags & F_is_identity) != 0) {
|
||||
_mat = LMatrix4f::ident_mat();
|
||||
|
||||
@ -639,6 +704,11 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
int flags = F_is_identity | F_singular_known;
|
||||
dg.add_uint16(flags);
|
||||
|
||||
} else if ((_flags & F_is_invalid) != 0) {
|
||||
// Invalid, nothing much to that either.
|
||||
int flags = F_is_invalid | F_singular_known | F_is_singular | F_components_known | F_mat_known;
|
||||
dg.add_uint16(flags);
|
||||
|
||||
} else if ((_flags & F_components_given) != 0) {
|
||||
// A component-based transform.
|
||||
int flags = F_components_given | F_components_known | F_has_components;
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
|
||||
PUBLISHED:
|
||||
static CPT(TransformState) make_identity();
|
||||
INLINE static CPT(TransformState) make_invalid();
|
||||
INLINE static CPT(TransformState) make_pos(const LVecBase3f &pos);
|
||||
INLINE static CPT(TransformState) make_hpr(const LVecBase3f &hpr);
|
||||
INLINE static CPT(TransformState) make_pos_hpr(const LVecBase3f &pos,
|
||||
@ -78,11 +79,14 @@ PUBLISHED:
|
||||
static CPT(TransformState) make_mat(const LMatrix4f &mat);
|
||||
|
||||
INLINE bool is_identity() const;
|
||||
INLINE bool is_invalid() const;
|
||||
INLINE bool is_singular() const;
|
||||
INLINE bool has_components() const;
|
||||
INLINE bool components_given() const;
|
||||
INLINE bool has_pos() const;
|
||||
INLINE bool has_hpr() const;
|
||||
INLINE bool has_scale() const;
|
||||
INLINE bool has_mat() const;
|
||||
INLINE const LVecBase3f &get_pos() const;
|
||||
INLINE const LVecBase3f &get_hpr() const;
|
||||
INLINE const LVecBase3f &get_scale() const;
|
||||
@ -149,6 +153,7 @@ private:
|
||||
F_components_known = 0x0010,
|
||||
F_has_components = 0x0020,
|
||||
F_mat_known = 0x0040,
|
||||
F_is_invalid = 0x0080,
|
||||
};
|
||||
LVecBase3f _pos, _hpr, _scale;
|
||||
LMatrix4f _mat;
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include "dSearchPath.h"
|
||||
#include "loader.h"
|
||||
#include "auto_bind.h"
|
||||
#include "pStatClient.h"
|
||||
#include "notify.h"
|
||||
#include "qpnodePath.h"
|
||||
#include "cullBinManager.h"
|
||||
|
||||
// These are in support of legacy data graph operations.
|
||||
#include "namedNode.h"
|
||||
@ -66,6 +70,12 @@ bool run_flag = true;
|
||||
static double start_time = 0.0;
|
||||
static int start_frame_count = 0;
|
||||
|
||||
// A priority number high enough to override any model file settings.
|
||||
static const int override_priority = 100;
|
||||
|
||||
// This is the main scene graph.
|
||||
qpNodePath render;
|
||||
|
||||
void
|
||||
report_frame_rate() {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
@ -95,15 +105,15 @@ make_pipe() {
|
||||
// load-display Configrc variable.
|
||||
GraphicsPipe::resolve_modules();
|
||||
|
||||
cerr << "Known pipe types:" << endl;
|
||||
GraphicsPipe::get_factory().write_types(cerr, 2);
|
||||
nout << "Known pipe types:" << endl;
|
||||
GraphicsPipe::get_factory().write_types(nout, 2);
|
||||
|
||||
PT(GraphicsPipe) pipe;
|
||||
pipe = GraphicsPipe::get_factory().
|
||||
make_instance(InteractiveGraphicsPipe::get_class_type());
|
||||
|
||||
if (pipe == (GraphicsPipe*)0L) {
|
||||
cerr << "No interactive pipe is available! Check your Configrc!\n";
|
||||
nout << "No interactive pipe is available! Check your Configrc!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -204,7 +214,7 @@ get_models(PandaNode *parent, int argc, char *argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
Filename filename = argv[i];
|
||||
|
||||
cerr << "Loading " << filename << "\n";
|
||||
nout << "Loading " << filename << "\n";
|
||||
|
||||
// First, we always try to resolve a filename from the current
|
||||
// directory. This means a local filename will always be found
|
||||
@ -213,10 +223,10 @@ get_models(PandaNode *parent, int argc, char *argv[]) {
|
||||
|
||||
PT(PandaNode) node = loader.qpload_sync(filename);
|
||||
if (node == (PandaNode *)NULL) {
|
||||
cerr << "Unable to load " << filename << "\n";
|
||||
nout << "Unable to load " << filename << "\n";
|
||||
|
||||
} else {
|
||||
node->ls(cerr, 0);
|
||||
node->ls(nout, 0);
|
||||
parent->add_child(node);
|
||||
}
|
||||
}
|
||||
@ -259,9 +269,81 @@ event_esc(CPT_Event) {
|
||||
|
||||
void
|
||||
event_f(CPT_Event) {
|
||||
// 'f' : report frame rate.
|
||||
report_frame_rate();
|
||||
}
|
||||
|
||||
void
|
||||
event_t(CPT_Event) {
|
||||
// 't' : toggle texture.
|
||||
static bool texture_off = false;
|
||||
|
||||
texture_off = !texture_off;
|
||||
if (texture_off) {
|
||||
nout << "Disabling texturing.\n";
|
||||
render.set_texture_off(override_priority);
|
||||
} else {
|
||||
nout << "Enabling texturing.\n";
|
||||
render.clear_texture();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_w(CPT_Event) {
|
||||
// 'w' : toggle wireframe.
|
||||
static bool wireframe = false;
|
||||
|
||||
wireframe = !wireframe;
|
||||
if (wireframe) {
|
||||
nout << "Setting wireframe mode.\n";
|
||||
render.set_render_mode_wireframe(override_priority);
|
||||
} else {
|
||||
nout << "Clearing wireframe mode.\n";
|
||||
render.clear_render_mode();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_s(CPT_Event) {
|
||||
// 's' : toggle state sorting by putting everything into an 'unsorted' bin.
|
||||
static bool sorting_off = false;
|
||||
|
||||
sorting_off = !sorting_off;
|
||||
if (sorting_off) {
|
||||
nout << "Disabling state sorting.\n";
|
||||
render.set_bin("unsorted", 0, override_priority);
|
||||
} else {
|
||||
nout << "Enabling state sorting.\n";
|
||||
render.clear_bin();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_S(CPT_Event) {
|
||||
// shift 'S' : active PStats.
|
||||
#ifdef DO_PSTATS
|
||||
nout << "Connecting to stats host" << endl;
|
||||
PStatClient::connect();
|
||||
#else
|
||||
nout << "Stats host not supported." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
event_A(CPT_Event) {
|
||||
// shift 'A' : deactive PStats.
|
||||
#ifdef DO_PSTATS
|
||||
if (PStatClient::is_connected()) {
|
||||
nout << "Disconnecting from stats host" << endl;
|
||||
PStatClient::disconnect();
|
||||
} else {
|
||||
nout << "Stats host is already disconnected." << endl;
|
||||
}
|
||||
#else
|
||||
nout << "Stats host not supported." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
// First, we need a GraphicsPipe, before we can open a window.
|
||||
@ -275,10 +357,14 @@ main(int argc, char *argv[]) {
|
||||
PT(qpCamera) camera = make_camera(window);
|
||||
|
||||
// Now we just need to make a scene graph for the camera to render.
|
||||
PT(PandaNode) render = new PandaNode("render");
|
||||
render->add_child(camera);
|
||||
render = qpNodePath(new PandaNode("render"));
|
||||
render.attach_new_node(camera);
|
||||
camera->set_scene(qpNodePath(render));
|
||||
|
||||
// We will take advantage of this bin if the user toggles state
|
||||
// sorting, above, in event_s().
|
||||
CullBinManager::get_global_ptr()->add_bin("unsorted", CullBinManager::BT_unsorted, 0);
|
||||
|
||||
// Set up a data graph for tracking user input. For now, this uses
|
||||
// the old-style graph interface.
|
||||
PT(NamedNode) data_root = new NamedNode("data_root");
|
||||
@ -290,16 +376,21 @@ main(int argc, char *argv[]) {
|
||||
event_handler.add_hook("escape", event_esc);
|
||||
event_handler.add_hook("q", event_esc);
|
||||
event_handler.add_hook("f", event_f);
|
||||
event_handler.add_hook("t", event_t);
|
||||
event_handler.add_hook("w", event_w);
|
||||
event_handler.add_hook("s", event_s);
|
||||
event_handler.add_hook("shift-s", event_S);
|
||||
event_handler.add_hook("shift-a", event_A);
|
||||
|
||||
|
||||
// Put something in the scene graph to look at.
|
||||
get_models(render, argc, argv);
|
||||
get_models(render.node(), argc, argv);
|
||||
|
||||
// If we happened to load up both a character file and its matching
|
||||
// animation file, attempt to bind them together now and start the
|
||||
// animations looping.
|
||||
AnimControlCollection anim_controls;
|
||||
auto_bind(render, anim_controls, ~0);
|
||||
auto_bind(render.node(), anim_controls, ~0);
|
||||
anim_controls.loop_all(true);
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user