00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "rigidBodyCombiner.h"
00016 #include "nodePath.h"
00017 #include "geomNode.h"
00018 #include "modelNode.h"
00019 #include "geomVertexData.h"
00020 #include "geomVertexFormat.h"
00021 #include "geomVertexArrayFormat.h"
00022 #include "geomVertexAnimationSpec.h"
00023 #include "sceneGraphReducer.h"
00024 #include "omniBoundingVolume.h"
00025
00026 TypeHandle RigidBodyCombiner::_type_handle;
00027
00028
00029
00030
00031
00032
00033
00034 RigidBodyCombiner::
00035 RigidBodyCombiner(const string &name) : PandaNode(name) {
00036 set_cull_callback();
00037
00038 _internal_root = new PandaNode(name);
00039
00040
00041
00042
00043
00044
00045 _internal_root->set_bounds(new OmniBoundingVolume);
00046 _internal_root->set_final(true);
00047 }
00048
00049
00050
00051
00052
00053
00054 RigidBodyCombiner::
00055 RigidBodyCombiner(const RigidBodyCombiner ©) : PandaNode(copy) {
00056 set_cull_callback();
00057
00058 _internal_root = copy._internal_root;
00059 _internal_transforms = copy._internal_transforms;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 PandaNode *RigidBodyCombiner::
00072 make_copy() const {
00073 return new RigidBodyCombiner(*this);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 void RigidBodyCombiner::
00101 collect() {
00102 _internal_root = new GeomNode(get_name());
00103 _internal_transforms.clear();
00104 _vd_table.clear();
00105
00106 Children cr = get_children();
00107 int num_children = cr.get_num_children();
00108 for (int i = 0; i < num_children; i++) {
00109 r_collect(cr.get_child(i), RenderState::make_empty(), NULL);
00110 }
00111
00112 _vd_table.clear();
00113
00114 SceneGraphReducer gr;
00115 gr.apply_attribs(_internal_root);
00116 gr.collect_vertex_data(_internal_root, ~(SceneGraphReducer::CVD_format | SceneGraphReducer::CVD_name | SceneGraphReducer::CVD_animation_type));
00117 gr.unify(_internal_root, false);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 NodePath RigidBodyCombiner::
00132 get_internal_scene() {
00133 return NodePath(_internal_root);
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 bool RigidBodyCombiner::
00162 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00163
00164
00165 Thread *current_thread = Thread::get_current_thread();
00166 Transforms::iterator ti;
00167 for (ti = _internal_transforms.begin();
00168 ti != _internal_transforms.end();
00169 ++ti) {
00170 (*ti)->mark_modified(current_thread);
00171 }
00172
00173
00174 CullTraverserData next_data(data, _internal_root);
00175 trav->traverse(next_data);
00176
00177
00178 return false;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 void RigidBodyCombiner::
00190 r_collect(PandaNode *node, const RenderState *state,
00191 const VertexTransform *transform) {
00192 CPT(RenderState) next_state = state->compose(node->get_state());
00193 CPT(VertexTransform) next_transform = transform;
00194 if (!node->get_transform()->is_identity() ||
00195 node->is_of_type(ModelNode::get_class_type()) &&
00196 DCAST(ModelNode, node)->get_preserve_transform() != ModelNode::PT_none) {
00197
00198 PT(NodeVertexTransform) new_transform = new NodeVertexTransform(node, transform);
00199 _internal_transforms.push_back(new_transform);
00200 next_transform = new_transform.p();
00201
00202 }
00203
00204 if (node->is_geom_node()) {
00205 GeomNode *gnode = DCAST(GeomNode, node);
00206 GeomNode *root_gnode = DCAST(GeomNode, _internal_root);
00207
00208 int num_geoms = gnode->get_num_geoms();
00209 for (int i = 0; i < num_geoms; ++i) {
00210 PT(Geom) geom = gnode->get_geom(i)->make_copy();
00211 if (next_transform != (const VertexTransform *)NULL) {
00212 geom->set_vertex_data(convert_vd(next_transform, geom->get_vertex_data()));
00213 }
00214 CPT(RenderState) gstate = next_state->compose(gnode->get_geom_state(i));
00215 root_gnode->add_geom(geom, gstate);
00216 }
00217 }
00218
00219 Children cr = node->get_children();
00220 int num_children = cr.get_num_children();
00221 for (int i = 0; i < num_children; i++) {
00222 r_collect(cr.get_child(i), next_state, next_transform);
00223 }
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 PT(GeomVertexData) RigidBodyCombiner::
00234 convert_vd(const VertexTransform *transform, const GeomVertexData *orig) {
00235
00236
00237
00238
00239 VDTable::iterator vdti = _vd_table.find(VDUnifier(transform, orig));
00240 if (vdti != _vd_table.end()) {
00241 return (*vdti).second;
00242 }
00243
00244 PT(GeomVertexFormat) format = new GeomVertexFormat(*orig->get_format());
00245 if (!orig->get_format()->has_column(InternalName::get_transform_blend())) {
00246 PT(GeomVertexArrayFormat) af =
00247 new GeomVertexArrayFormat(InternalName::get_transform_blend(), 1,
00248 Geom::NT_uint16, Geom::C_index);
00249 format->add_array(af);
00250 }
00251
00252 GeomVertexAnimationSpec spec;
00253 spec.set_panda();
00254 format->set_animation(spec);
00255 format->maybe_align_columns_for_animation();
00256
00257 CPT(GeomVertexFormat) new_format = GeomVertexFormat::register_format(format);
00258 CPT(GeomVertexData) converted = orig->convert_to(new_format);
00259 PT(GeomVertexData) new_data = new GeomVertexData(*converted);
00260
00261 if (new_data->get_transform_blend_table() == (TransformBlendTable *)NULL) {
00262
00263
00264 PT(TransformBlendTable) new_table = new TransformBlendTable;
00265 new_table->add_blend(TransformBlend(transform, 1.0f));
00266 new_table->set_rows(SparseArray::range(0, new_data->get_num_rows()));
00267 new_data->set_transform_blend_table(new_table);
00268 } else {
00269
00270
00271 }
00272
00273
00274 _vd_table[VDUnifier(transform, orig)] = new_data;
00275
00276 return new_data;
00277 }