| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | #include <osg/Transform> |
|---|
| 14 | #include <osg/Camera> |
|---|
| 15 | |
|---|
| 16 | #include <osg/Notify> |
|---|
| 17 | |
|---|
| 18 | using namespace osg; |
|---|
| 19 | |
|---|
| 20 | class TransformVisitor : public NodeVisitor |
|---|
| 21 | { |
|---|
| 22 | public: |
|---|
| 23 | |
|---|
| 24 | enum CoordMode |
|---|
| 25 | { |
|---|
| 26 | WORLD_TO_LOCAL, |
|---|
| 27 | LOCAL_TO_WORLD |
|---|
| 28 | }; |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | CoordMode _coordMode; |
|---|
| 32 | Matrix& _matrix; |
|---|
| 33 | bool _ignoreCameras; |
|---|
| 34 | |
|---|
| 35 | TransformVisitor(Matrix& matrix,CoordMode coordMode, bool ignoreCameras): |
|---|
| 36 | NodeVisitor(), |
|---|
| 37 | _coordMode(coordMode), |
|---|
| 38 | _matrix(matrix), |
|---|
| 39 | _ignoreCameras(ignoreCameras) |
|---|
| 40 | {} |
|---|
| 41 | |
|---|
| 42 | virtual void apply(Transform& transform) |
|---|
| 43 | { |
|---|
| 44 | if (_coordMode==LOCAL_TO_WORLD) |
|---|
| 45 | { |
|---|
| 46 | transform.computeLocalToWorldMatrix(_matrix,this); |
|---|
| 47 | } |
|---|
| 48 | else |
|---|
| 49 | { |
|---|
| 50 | transform.computeWorldToLocalMatrix(_matrix,this); |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | void accumulate(const NodePath& nodePath) |
|---|
| 55 | { |
|---|
| 56 | if (nodePath.empty()) return; |
|---|
| 57 | |
|---|
| 58 | unsigned int i = 0; |
|---|
| 59 | if (_ignoreCameras) |
|---|
| 60 | { |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | i = nodePath.size(); |
|---|
| 64 | NodePath::const_reverse_iterator ritr; |
|---|
| 65 | for(ritr = nodePath.rbegin(); |
|---|
| 66 | ritr != nodePath.rend(); |
|---|
| 67 | ++ritr, --i) |
|---|
| 68 | { |
|---|
| 69 | const osg::Camera* camera = dynamic_cast<const osg::Camera*>(*ritr); |
|---|
| 70 | if (camera && |
|---|
| 71 | (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) |
|---|
| 72 | { |
|---|
| 73 | break; |
|---|
| 74 | } |
|---|
| 75 | } |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | |
|---|
| 79 | for(; |
|---|
| 80 | i<nodePath.size(); |
|---|
| 81 | ++i) |
|---|
| 82 | { |
|---|
| 83 | const_cast<Node*>(nodePath[i])->accept(*this); |
|---|
| 84 | } |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | protected: |
|---|
| 88 | |
|---|
| 89 | TransformVisitor& operator = (const TransformVisitor&) { return *this; } |
|---|
| 90 | |
|---|
| 91 | }; |
|---|
| 92 | |
|---|
| 93 | Matrix osg::computeLocalToWorld(const NodePath& nodePath, bool ignoreCameras) |
|---|
| 94 | { |
|---|
| 95 | Matrix matrix; |
|---|
| 96 | TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD,ignoreCameras); |
|---|
| 97 | tv.accumulate(nodePath); |
|---|
| 98 | return matrix; |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | Matrix osg::computeWorldToLocal(const NodePath& nodePath, bool ignoreCameras) |
|---|
| 102 | { |
|---|
| 103 | osg::Matrix matrix; |
|---|
| 104 | TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL,ignoreCameras); |
|---|
| 105 | tv.accumulate(nodePath); |
|---|
| 106 | return matrix; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | Matrix osg::computeLocalToEye(const Matrix& modelview,const NodePath& nodePath, bool ignoreCameras) |
|---|
| 110 | { |
|---|
| 111 | Matrix matrix(modelview); |
|---|
| 112 | TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD,ignoreCameras); |
|---|
| 113 | tv.accumulate(nodePath); |
|---|
| 114 | return matrix; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | Matrix osg::computeEyeToLocal(const Matrix& modelview,const NodePath& nodePath, bool ignoreCameras) |
|---|
| 118 | { |
|---|
| 119 | Matrix matrix; |
|---|
| 120 | matrix.invert(modelview); |
|---|
| 121 | TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL,ignoreCameras); |
|---|
| 122 | tv.accumulate(nodePath); |
|---|
| 123 | return matrix; |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | |
|---|
| 127 | |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | Transform::Transform() |
|---|
| 131 | { |
|---|
| 132 | _referenceFrame = RELATIVE_RF; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | Transform::Transform(const Transform& transform,const CopyOp& copyop): |
|---|
| 136 | Group(transform,copyop), |
|---|
| 137 | _referenceFrame(transform._referenceFrame) |
|---|
| 138 | { |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | Transform::~Transform() |
|---|
| 142 | { |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | void Transform::setReferenceFrame(ReferenceFrame rf) |
|---|
| 146 | { |
|---|
| 147 | if (_referenceFrame == rf) return; |
|---|
| 148 | |
|---|
| 149 | _referenceFrame = rf; |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | setCullingActive(_referenceFrame==RELATIVE_RF); |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | BoundingSphere Transform::computeBound() const |
|---|
| 156 | { |
|---|
| 157 | BoundingSphere bsphere = Group::computeBound(); |
|---|
| 158 | if (!bsphere.valid()) return bsphere; |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | Matrix l2w; |
|---|
| 163 | |
|---|
| 164 | computeLocalToWorldMatrix(l2w,NULL); |
|---|
| 165 | |
|---|
| 166 | osg::BoundingSphere::vec_type xdash = bsphere._center; |
|---|
| 167 | xdash.x() += bsphere._radius; |
|---|
| 168 | xdash = xdash*l2w; |
|---|
| 169 | |
|---|
| 170 | osg::BoundingSphere::vec_type ydash = bsphere._center; |
|---|
| 171 | ydash.y() += bsphere._radius; |
|---|
| 172 | ydash = ydash*l2w; |
|---|
| 173 | |
|---|
| 174 | osg::BoundingSphere::vec_type zdash = bsphere._center; |
|---|
| 175 | zdash.z() += bsphere._radius; |
|---|
| 176 | zdash = zdash*l2w; |
|---|
| 177 | |
|---|
| 178 | bsphere._center = bsphere._center*l2w; |
|---|
| 179 | |
|---|
| 180 | xdash -= bsphere._center; |
|---|
| 181 | osg::BoundingSphere::value_type len_xdash = xdash.length(); |
|---|
| 182 | |
|---|
| 183 | ydash -= bsphere._center; |
|---|
| 184 | osg::BoundingSphere::value_type len_ydash = ydash.length(); |
|---|
| 185 | |
|---|
| 186 | zdash -= bsphere._center; |
|---|
| 187 | osg::BoundingSphere::value_type len_zdash = zdash.length(); |
|---|
| 188 | |
|---|
| 189 | bsphere._radius = len_xdash; |
|---|
| 190 | if (bsphere._radius<len_ydash) bsphere._radius = len_ydash; |
|---|
| 191 | if (bsphere._radius<len_zdash) bsphere._radius = len_zdash; |
|---|
| 192 | |
|---|
| 193 | return bsphere; |
|---|
| 194 | |
|---|
| 195 | } |
|---|