Selaa lähdekoodia

pgraph: Support hardware instancing in BillboardEffect and CompassEffect

rdb 5 vuotta sitten
vanhempi
sitoutus
e13756f43e
2 muutettua tiedostoa jossa 69 lisäystä ja 15 poistoa
  1. 19 1
      panda/src/pgraph/billboardEffect.cxx
  2. 50 14
      panda/src/pgraph/compassEffect.cxx

+ 19 - 1
panda/src/pgraph/billboardEffect.cxx

@@ -140,7 +140,25 @@ cull_callback(CullTraverser *trav, CullTraverserData &data,
     camera_transform = trav->get_camera_transform()->invert_compose(_look_at.get_net_transform());
     camera_transform = trav->get_camera_transform()->invert_compose(_look_at.get_net_transform());
   }
   }
 
 
-  compute_billboard(node_transform, modelview_transform, camera_transform);
+  if (data._instances == nullptr) {
+    compute_billboard(node_transform, modelview_transform, camera_transform);
+  }
+  else {
+    // Compute the billboard effect for every instance individually.
+    InstanceList *instances = new InstanceList(*data._instances);
+    data._instances = instances;
+
+    for (InstanceList::Instance &instance : *instances) {
+      CPT(TransformState) inst_node_transform = node_transform;
+      CPT(TransformState) inst_modelview_transform = modelview_transform->compose(instance.get_transform());
+      compute_billboard(inst_node_transform, inst_modelview_transform, camera_transform);
+
+      instance.set_transform(instance.get_transform()->compose(inst_node_transform));
+    }
+
+    // We've already applied this onto the instances.
+    node_transform = TransformState::make_identity();
+  }
 }
 }
 
 
 /**
 /**

+ 50 - 14
panda/src/pgraph/compassEffect.cxx

@@ -120,20 +120,56 @@ cull_callback(CullTraverser *trav, CullTraverserData &data,
     return;
     return;
   }
   }
 
 
-  CPT(TransformState) true_net_transform = data.get_net_transform(trav);
-  CPT(TransformState) want_net_transform = true_net_transform;
-  adjust_transform(want_net_transform, node_transform, data.node());
-
-  // Now compute the transform that will convert true_net_transform to
-  // want_transform.  This is inv(true_net_transform) * want_transform.
-  CPT(TransformState) compass_transform =
-    true_net_transform->invert_compose(want_net_transform);
-
-  // And modify our local node's apparent transform so that
-  // true_net_transform->compose(new_node_transform) produces the same result
-  // we would have gotten had we actually computed
-  // want_transform->compose(orig_node_transform).
-  node_transform = compass_transform->compose(node_transform);
+  if (data._instances == nullptr) {
+    CPT(TransformState) true_net_transform = data.get_net_transform(trav);
+    CPT(TransformState) want_net_transform = true_net_transform;
+    adjust_transform(want_net_transform, node_transform, data.node());
+
+    // Now compute the transform that will convert true_net_transform to
+    // want_transform.  This is inv(true_net_transform) * want_transform.
+    CPT(TransformState) compass_transform =
+      true_net_transform->invert_compose(want_net_transform);
+
+    // And modify our local node's apparent transform so that
+    // true_net_transform->compose(new_node_transform) produces the same result
+    // we would have gotten had we actually computed
+    // want_transform->compose(orig_node_transform).
+    node_transform = compass_transform->compose(node_transform);
+  }
+  else {
+    // Compute the billboard effect for every instance individually.
+    InstanceList *instances = new InstanceList(*data._instances);
+    data._instances = instances;
+
+    CPT(TransformState) parent_net_transform = data.get_net_transform(trav);
+    CPT(TransformState) invert_net_transform = parent_net_transform->get_inverse();
+
+    // We make use of the fact that we know adjust_transform() does not modify
+    // its node_transform parameter.
+    CPT(TransformState) node_transform_copy = node_transform;
+    if (node_transform_copy->is_identity()) {
+      // Slightly optimized case.
+      for (InstanceList::Instance &instance : *instances) {
+        CPT(TransformState) true_net_transform = parent_net_transform->compose(instance.get_transform());
+        CPT(TransformState) want_net_transform = true_net_transform;
+        adjust_transform(want_net_transform, node_transform_copy, data.node());
+
+        instance.set_transform(invert_net_transform->compose(want_net_transform));
+      }
+    }
+    else {
+      // We apply the node_transform to the instances.
+      node_transform = TransformState::make_identity();
+
+      for (InstanceList::Instance &instance : *instances) {
+        CPT(TransformState) true_net_transform = parent_net_transform->compose(instance.get_transform());
+        CPT(TransformState) want_net_transform = true_net_transform;
+        adjust_transform(want_net_transform, node_transform_copy, data.node());
+
+        instance.set_transform(invert_net_transform->compose(want_net_transform)->compose(node_transform_copy));
+      }
+    }
+  }
 }
 }
 
 
 /**
 /**