diff --git a/panda/src/pgraph/billboardEffect.cxx b/panda/src/pgraph/billboardEffect.cxx index ff44e11202..ab87da313a 100644 --- a/panda/src/pgraph/billboardEffect.cxx +++ b/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()); } - 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(); + } } /** diff --git a/panda/src/pgraph/compassEffect.cxx b/panda/src/pgraph/compassEffect.cxx index fe39b03bf3..db216af0d1 100644 --- a/panda/src/pgraph/compassEffect.cxx +++ b/panda/src/pgraph/compassEffect.cxx @@ -120,20 +120,56 @@ cull_callback(CullTraverser *trav, CullTraverserData &data, 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()); + 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); + // 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); + // 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)); + } + } + } } /**