Browse Source

added offset to billboard

David Rose 24 years ago
parent
commit
85e54125fa

+ 43 - 3
panda/src/sgattrib/billboardTransition.I

@@ -13,6 +13,7 @@ BillboardTransition() {
   _up_vector = LVector3f::up();
   _eye_relative = false;
   _axial_rotate = true;
+  _offset = 0.0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -23,11 +24,12 @@ BillboardTransition() {
 //               appropriate to the given coordinate system.
 ////////////////////////////////////////////////////////////////////
 INLINE BillboardTransition BillboardTransition::
-axis(CoordinateSystem cs) {
+axis(float offset, CoordinateSystem cs) {
   BillboardTransition t;
   t.set_up_vector(LVector3f::up(cs));
   t.set_eye_relative(false);
   t.set_axial_rotate(true);
+  t.set_offset(offset);
   return t;
 }
 
@@ -39,11 +41,12 @@ axis(CoordinateSystem cs) {
 //               (camera) coordinates.
 ////////////////////////////////////////////////////////////////////
 INLINE BillboardTransition BillboardTransition::
-point_eye(CoordinateSystem cs) {
+point_eye(float offset, CoordinateSystem cs) {
   BillboardTransition t;
   t.set_up_vector(LVector3f::up(cs));
   t.set_eye_relative(true);
   t.set_axial_rotate(false);
+  t.set_offset(offset);
   return t;
 }
 
@@ -55,11 +58,12 @@ point_eye(CoordinateSystem cs) {
 //               coordinates.
 ////////////////////////////////////////////////////////////////////
 INLINE BillboardTransition BillboardTransition::
-point_world(CoordinateSystem cs) {
+point_world(float offset, CoordinateSystem cs) {
   BillboardTransition t;
   t.set_up_vector(LVector3f::up(cs));
   t.set_eye_relative(false);
   t.set_axial_rotate(false);
+  t.set_offset(offset);
   return t;
 }
 
@@ -141,3 +145,39 @@ INLINE bool BillboardTransition::
 get_axial_rotate() const {
   return _axial_rotate;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: BillboardTransition::set_offset
+//       Access: Public
+//  Description: Sets a linear offset in the billboard.  This is
+//               particularly useful when eye_relative is true (which
+//               means the billboard rotates towards the camera plane,
+//               instead of towards the camera point).
+//
+//               The billboard geometry is first rotated
+//               appropriately, and then translated along the linear
+//               offset directly towards the camera.
+//
+//               This can be used to allow billboarding geometry to
+//               appear to float in front of an object, while not
+//               drifting away from the object as the object goes
+//               off-axis.  Another way to achieve the same effect is
+//               to simply translate the billboarding geometry by some
+//               linear distance along the z axis before making it a
+//               billboard, but this does not work in eye_relative
+//               mode.
+////////////////////////////////////////////////////////////////////
+INLINE void BillboardTransition::
+set_offset(float offset) {
+  _offset = offset;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BillboardTransition::get_axial_rotate
+//       Access: Public
+//  Description: See set_offset().
+////////////////////////////////////////////////////////////////////
+INLINE float BillboardTransition::
+get_offset() const {
+  return _offset;
+}

+ 18 - 9
panda/src/sgattrib/billboardTransition.cxx

@@ -40,7 +40,7 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 bool BillboardTransition::
 sub_render(NodeRelation *arc, const AllAttributesWrapper &,
-       AllTransitionsWrapper &trans, RenderTraverser *trav) {
+           AllTransitionsWrapper &trans, RenderTraverser *trav) {
   Node *node = arc->get_child();
   GraphicsStateGuardian *gsg = trav->get_gsg();
 
@@ -61,7 +61,7 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &,
     rel_mat = tt->get_matrix();
   }
 
-  LVector3f camera_pos,up;
+  LVector3f camera_pos, up;
 
   CoordinateSystem coordsys = gsg->get_coordinate_system();
 
@@ -71,18 +71,18 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &,
   // perpendicular to the forward direction, not directly to the
   // camera.
 
-
   if (_eye_relative) {
     up = _up_vector * rel_mat;
     camera_pos = LVector3f::forward(coordsys) * rel_mat;
-  } else {
-//    camera_pos= -rel_mat.get_row3(3);
 
-      camera_pos[0] = -rel_mat(3,0);
-      camera_pos[1] = -rel_mat(3,1);
-      camera_pos[2] = -rel_mat(3,2);
+  } else {
+//  camera_pos= -rel_mat.get_row3(3);
 
-      up = _up_vector;
+    camera_pos[0] = -rel_mat(3,0);
+    camera_pos[1] = -rel_mat(3,1);
+    camera_pos[2] = -rel_mat(3,2);
+    
+    up = _up_vector;
   }
 
   // Now determine the rotation matrix for the Billboard.
@@ -93,6 +93,15 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &,
     look_at(rotate, camera_pos, up, coordsys);
   }
 
+  // Also slide the billboard geometry towards the camera according to
+  // the offset factor.
+  if (_offset != 0.0f) {
+    LVector3f translate(rel_mat(3, 0), rel_mat(3, 1), rel_mat(3, 2));
+    translate.normalize();
+    translate *= _offset;
+    rotate.set_row(3, translate);
+  }
+
   // And finally, apply the rotation transform to the set of
   // transitions we've accumulated for this node.
   AllTransitionsWrapper new_trans;

+ 7 - 3
panda/src/sgattrib/billboardTransition.h

@@ -27,9 +27,9 @@
 class EXPCL_PANDA BillboardTransition : public ImmediateTransition {
 public:
   INLINE BillboardTransition();
-  INLINE static BillboardTransition axis(CoordinateSystem cs = CS_default);
-  INLINE static BillboardTransition point_eye(CoordinateSystem cs = CS_default);
-  INLINE static BillboardTransition point_world(CoordinateSystem cs = CS_default);
+  INLINE static BillboardTransition axis(float offset = 0.0, CoordinateSystem cs = CS_default);
+  INLINE static BillboardTransition point_eye(float offset = 0.0, CoordinateSystem cs = CS_default);
+  INLINE static BillboardTransition point_world(float offset = 0.0, CoordinateSystem cs = CS_default);
 
   INLINE void set_up_vector(const LVector3f &up_vector);
   INLINE LVector3f get_up_vector() const;
@@ -40,6 +40,9 @@ public:
   INLINE void set_axial_rotate(bool axial_rotate);
   INLINE bool get_axial_rotate() const;
 
+  INLINE void set_offset(float offset);
+  INLINE float get_offset() const;
+
   virtual NodeTransition *make_copy() const;
 
   virtual bool sub_render(NodeRelation *arc,
@@ -58,6 +61,7 @@ private:
   LVector3f _up_vector;
   bool _eye_relative;
   bool _axial_rotate;
+  float _offset;
 
 public:
   static void register_with_read_factory(void);