Browse Source

motiontrail: Calculate bounding volume much more efficiently

A lot of time was going into updating the bounding volume.
rdb 3 years ago
parent
commit
e08a502c88

+ 1 - 0
direct/src/motiontrail/MotionTrail.py

@@ -141,6 +141,7 @@ class MotionTrail(NodePath, DirectObject):
         ## parented to the MotionTrail itself, but can be reparented elsewhere
         ## parented to the MotionTrail itself, but can be reparented elsewhere
         ## if necessary.
         ## if necessary.
         self.geom_node = GeomNode("motion_trail")
         self.geom_node = GeomNode("motion_trail")
+        self.geom_node.setBoundsType(BoundingVolume.BT_box)
         self.geom_node_path = self.attachNewNode(self.geom_node)
         self.geom_node_path = self.attachNewNode(self.geom_node)
         node_path = self.geom_node_path
         node_path = self.geom_node_path
 
 

+ 38 - 2
direct/src/motiontrail/cMotionTrail.cxx

@@ -14,6 +14,7 @@
 #include "directbase.h"
 #include "directbase.h"
 #include "cMotionTrail.h"
 #include "cMotionTrail.h"
 #include "renderState.h"
 #include "renderState.h"
+#include "boundingBox.h"
 #include "colorAttrib.h"
 #include "colorAttrib.h"
 #include "cmath.h"
 #include "cmath.h"
 
 
@@ -73,6 +74,10 @@ add_vertex(const LVector4 &vertex, const LVector4 &start_color,
   motion_trail_vertex._v = v;
   motion_trail_vertex._v = v;
   motion_trail_vertex._nurbs_curve_evaluator = new NurbsCurveEvaluator();
   motion_trail_vertex._nurbs_curve_evaluator = new NurbsCurveEvaluator();
   _vertex_list.push_back(std::move(motion_trail_vertex));
   _vertex_list.push_back(std::move(motion_trail_vertex));
+
+  // Store the maximum distance from the origin, so we can calculate the bounds
+  // of the trail efficiently.
+  _vertex_bounds_radius = std::max(_vertex_bounds_radius, vertex.length());
 }
 }
 
 
 /**
 /**
@@ -230,7 +235,7 @@ add_geometry_quad(
  *
  *
  */
  */
 void CMotionTrail::
 void CMotionTrail::
-end_geometry() {
+end_geometry(const LPoint3 &min_vertex, const LPoint3 &max_vertex) {
   static CPT(RenderState) state;
   static CPT(RenderState) state;
   if (state == nullptr) {
   if (state == nullptr) {
     state = RenderState::make(ColorAttrib::make_vertex());
     state = RenderState::make(ColorAttrib::make_vertex());
@@ -240,7 +245,12 @@ end_geometry() {
   _color_writer.clear();
   _color_writer.clear();
   _texture_writer.clear();
   _texture_writer.clear();
 
 
+  PT(BoundingBox) bounds = new BoundingBox(
+    min_vertex - LVector3(_vertex_bounds_radius * 2),
+    max_vertex + LVector3(_vertex_bounds_radius * 2));
+
   PT(Geom) geometry = new Geom(_vertex_data);
   PT(Geom) geometry = new Geom(_vertex_data);
+  geometry->set_bounds(bounds);
   geometry->add_primitive(_triangles);
   geometry->add_primitive(_triangles);
 
 
   if (_geom_node) {
   if (_geom_node) {
@@ -319,6 +329,8 @@ update_motion_trail(PN_stdfloat current_time, const LMatrix4 &transform) {
     PN_stdfloat delta_time;
     PN_stdfloat delta_time;
     CMotionTrailFrame last_motion_trail_frame;
     CMotionTrailFrame last_motion_trail_frame;
 
 
+    LPoint3 min_vertex, max_vertex;
+
     VertexList::iterator vertex_iterator;
     VertexList::iterator vertex_iterator;
 
 
     // convert vertex list to vertex array
     // convert vertex list to vertex array
@@ -383,6 +395,18 @@ update_motion_trail(PN_stdfloat current_time, const LMatrix4 &transform) {
         nurbs_curve_evaluator = motion_trail_vertex_start->_nurbs_curve_evaluator;
         nurbs_curve_evaluator = motion_trail_vertex_start->_nurbs_curve_evaluator;
         nurbs_curve_evaluator->set_vertex(segment_index, v0);
         nurbs_curve_evaluator->set_vertex(segment_index, v0);
 
 
+        // For efficiency, calculate this only for the first vertex, we add the
+        // diameter of the cross-section to this later.
+        if (segment_index == 0) {
+          min_vertex = v0.get_xyz();
+          max_vertex = min_vertex;
+        } else {
+          min_vertex = min_vertex.fmin(v0.get_xyz());
+          max_vertex = max_vertex.fmax(v0.get_xyz());
+        }
+        min_vertex = min_vertex.fmin(v2.get_xyz());
+        max_vertex = max_vertex.fmax(v2.get_xyz());
+
         for (int vertex_segment_index = 0;
         for (int vertex_segment_index = 0;
              vertex_segment_index < total_vertex_segments;
              vertex_segment_index < total_vertex_segments;
              ++vertex_segment_index) {
              ++vertex_segment_index) {
@@ -575,6 +599,18 @@ update_motion_trail(PN_stdfloat current_time, const LMatrix4 &transform) {
         t0.set(st, motion_trail_vertex_start->_v);
         t0.set(st, motion_trail_vertex_start->_v);
         t2.set(et, motion_trail_vertex_start->_v);
         t2.set(et, motion_trail_vertex_start->_v);
 
 
+        // For efficiency, calculate this only for the first vertex, we add the
+        // diameter of the cross-section to this later.
+        if (segment_index == 0) {
+          min_vertex = v0.get_xyz();
+          max_vertex = min_vertex;
+        } else {
+          min_vertex = min_vertex.fmin(v0.get_xyz());
+          max_vertex = max_vertex.fmax(v0.get_xyz());
+        }
+        min_vertex = min_vertex.fmin(v2.get_xyz());
+        max_vertex = max_vertex.fmax(v2.get_xyz());
+
         for (int vertex_segment_index = 0;
         for (int vertex_segment_index = 0;
              vertex_segment_index < total_vertex_segments;
              vertex_segment_index < total_vertex_segments;
              ++vertex_segment_index) {
              ++vertex_segment_index) {
@@ -611,7 +647,7 @@ update_motion_trail(PN_stdfloat current_time, const LMatrix4 &transform) {
       }
       }
     }
     }
 
 
-    end_geometry();
+    end_geometry(min_vertex, max_vertex);
 
 
     delete[] vertex_array;
     delete[] vertex_array;
   }
   }

+ 2 - 1
direct/src/motiontrail/cMotionTrail.h

@@ -94,7 +94,7 @@ public:
     const LPoint3 &v0, const LPoint3 &v1, const LPoint3 &v2, const LPoint3 &v3,
     const LPoint3 &v0, const LPoint3 &v1, const LPoint3 &v2, const LPoint3 &v3,
     const LVector4 &c0, const LVector4 &c1, const LVector4 &c2, const LVector4 &c3,
     const LVector4 &c0, const LVector4 &c1, const LVector4 &c2, const LVector4 &c3,
     const LVector2 &t0, const LVector2 &t1, const LVector2 &t2, const LVector2 &t3);
     const LVector2 &t0, const LVector2 &t1, const LVector2 &t2, const LVector2 &t3);
-  void end_geometry();
+  void end_geometry(const LPoint3 &min_vertex, const LPoint3 &max_vertex);
 
 
   bool _active = true;
   bool _active = true;
   bool _enable = true;
   bool _enable = true;
@@ -114,6 +114,7 @@ public:
   VertexList _vertex_list;
   VertexList _vertex_list;
   typedef pdeque<CMotionTrailFrame> FrameList;
   typedef pdeque<CMotionTrailFrame> FrameList;
   FrameList _frame_list;
   FrameList _frame_list;
+  PN_stdfloat _vertex_bounds_radius = 0.0f;
 
 
   // parameters
   // parameters
   PN_stdfloat _color_scale = 1.0f;
   PN_stdfloat _color_scale = 1.0f;