Panda3D
eggSaver.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file eggSaver.cxx
10  * @author drose
11  * @date 2012-12-19
12  */
13 
14 #include "eggSaver.h"
15 
16 #include "pandaNode.h"
17 #include "workingNodePath.h"
18 #include "nodePath.h"
19 #include "billboardEffect.h"
20 #include "renderEffects.h"
21 #include "transformState.h"
22 #include "colorScaleAttrib.h"
23 #include "colorAttrib.h"
24 #include "materialAttrib.h"
25 #include "textureAttrib.h"
26 #include "cullBinAttrib.h"
27 #include "cullFaceAttrib.h"
28 #include "transparencyAttrib.h"
29 #include "depthTestAttrib.h"
30 #include "depthOffsetAttrib.h"
31 #include "depthWriteAttrib.h"
32 #include "lodNode.h"
33 #include "switchNode.h"
34 #include "sequenceNode.h"
35 #include "uvScrollNode.h"
36 #include "collisionNode.h"
37 #include "collisionPolygon.h"
38 #include "collisionPlane.h"
39 #include "collisionSphere.h"
40 #include "collisionBox.h"
41 #include "collisionInvSphere.h"
42 #include "collisionCapsule.h"
43 #include "textureStage.h"
44 #include "geomNode.h"
45 #include "geom.h"
46 #include "geomTriangles.h"
47 #include "geomPatches.h"
48 #include "geomPoints.h"
49 #include "geomLines.h"
50 #include "geomVertexReader.h"
51 #include "transformTable.h"
52 #include "modelNode.h"
53 #include "animBundleNode.h"
55 #include "characterJoint.h"
56 #include "character.h"
57 #include "string_utils.h"
58 #include "bamFile.h"
59 #include "bamCacheRecord.h"
60 #include "eggSAnimData.h"
61 #include "eggXfmAnimData.h"
62 #include "eggXfmSAnim.h"
63 #include "eggGroup.h"
64 #include "eggVertexPool.h"
65 #include "eggVertex.h"
66 #include "eggPrimitive.h"
67 #include "eggPolygon.h"
68 #include "eggPatch.h"
69 #include "eggPoint.h"
70 #include "eggLine.h"
71 #include "eggTexture.h"
72 #include "eggMaterial.h"
73 #include "eggRenderMode.h"
74 #include "eggTable.h"
75 #include "dcast.h"
76 
77 using std::pair;
78 using std::string;
79 
80 /**
81  *
82  */
83 EggSaver::
84 EggSaver(EggData *data) :
85  _data(data)
86 {
87  if (_data == nullptr) {
88  _data = new EggData;
89  }
90 }
91 
92 /**
93  * Adds the scene graph rooted at the indicated node to the accumulated egg
94  * data within this object. Call get_egg_data() to retrieve the result.
95  */
97 add_node(PandaNode *node) {
98  _vpool = new EggVertexPool(node->get_name());
99  _data->add_child(_vpool);
100 
101  NodePath root(node);
102  convert_node(WorkingNodePath(root), _data, false, nullptr);
103 
104  // Remove the vertex pool if it has no vertices.
105  if (_vpool->empty()) {
106  _data->remove_child(_vpool);
107  }
108  _vpool = nullptr;
109 }
110 
111 /**
112  * Adds the scene graph rooted at the indicated node (but without the node
113  * itself) to the accumulated egg data within this object. Call
114  * get_egg_data() to retrieve the result.
115  */
117 add_subgraph(PandaNode *root) {
118  _vpool = new EggVertexPool(root->get_name());
119  _data->add_child(_vpool);
120 
121  NodePath root_path(root);
122  recurse_nodes(root_path, _data, false, nullptr);
123 
124  // Remove the vertex pool if it has no vertices.
125  if (_vpool->empty()) {
126  _data->remove_child(_vpool);
127  }
128  _vpool = nullptr;
129 }
130 
131 /**
132  * Converts the indicated node to the corresponding Egg constructs, by first
133  * determining what kind of node it is.
134  */
135 void EggSaver::
136 convert_node(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
137  bool has_decal, CharacterJointMap *joint_map) {
138  PandaNode *node = node_path.node();
139  if (node->is_geom_node()) {
140  convert_geom_node(DCAST(GeomNode, node), node_path, egg_parent, has_decal, joint_map);
141 
142  } else if (node->is_of_type(LODNode::get_class_type())) {
143  convert_lod_node(DCAST(LODNode, node), node_path, egg_parent, has_decal, joint_map);
144 
145  } else if (node->is_of_type(SequenceNode::get_class_type())) {
146  convert_sequence_node(DCAST(SequenceNode, node), node_path, egg_parent, has_decal, joint_map);
147 
148  } else if (node->is_of_type(SwitchNode::get_class_type())) {
149  convert_switch_node(DCAST(SwitchNode, node), node_path, egg_parent, has_decal, joint_map);
150 
151  } else if (node->is_of_type(CollisionNode::get_class_type())) {
152  convert_collision_node(DCAST(CollisionNode, node), node_path, egg_parent, has_decal, joint_map);
153 
154  } else if (node->is_of_type(AnimBundleNode::get_class_type())) {
155  convert_anim_node(DCAST(AnimBundleNode, node), node_path, egg_parent, has_decal);
156 
157  } else if (node->is_of_type(Character::get_class_type())) {
158  convert_character_node(DCAST(Character, node), node_path, egg_parent, has_decal);
159 
160  } else {
161  // Just a generic node.
162  EggGroup *egg_group = new EggGroup(node->get_name());
163  egg_parent->add_child(egg_group);
164  apply_node_properties(egg_group, node);
165 
166  recurse_nodes(node_path, egg_group, has_decal, joint_map);
167  }
168 }
169 
170 /**
171  * Converts the indicated LODNode to the corresponding Egg constructs.
172  */
173 void EggSaver::
174 convert_lod_node(LODNode *node, const WorkingNodePath &node_path,
175  EggGroupNode *egg_parent, bool has_decal,
176  CharacterJointMap *joint_map) {
177  // An LOD node gets converted to an ordinary EggGroup, but we apply the
178  // appropriate switch conditions to each of our children.
179  EggGroup *egg_group = new EggGroup(node->get_name());
180  egg_parent->add_child(egg_group);
181  apply_node_properties(egg_group, node);
182 
183  int num_children = node->get_num_children();
184  int num_switches = node->get_num_switches();
185 
186  num_children = std::min(num_children, num_switches);
187 
188  for (int i = 0; i < num_children; i++) {
189  PandaNode *child = node->get_child(i);
190 
191  // Convert just this one node to an EggGroup.
192  PT(EggGroup) next_group = new EggGroup;
193  convert_node(WorkingNodePath(node_path, child), next_group, has_decal, joint_map);
194 
195  if (next_group->size() == 1) {
196  // If we have exactly one child, and that child is an EggGroup,
197  // collapse.
198  EggNode *child_node = *next_group->begin();
199  if (child_node->is_of_type(EggGroup::get_class_type())) {
200  PT(EggGroup) child = DCAST(EggGroup, child_node);
201  next_group->remove_child(child.p());
202  next_group = child;
203  }
204  }
205 
206  // Now set up the switching properties appropriately.
207  PN_stdfloat in = node->get_in(i);
208  PN_stdfloat out = node->get_out(i);
209  LPoint3 center = node->get_center();
210  EggSwitchConditionDistance dist(in, out, LCAST(double, center));
211  next_group->set_lod(dist);
212  egg_group->add_child(next_group.p());
213  }
214 }
215 
216 /**
217  * Converts the indicated SequenceNode to the corresponding Egg constructs.
218  */
219 void EggSaver::
220 convert_sequence_node(SequenceNode *node, const WorkingNodePath &node_path,
221  EggGroupNode *egg_parent, bool has_decal,
222  CharacterJointMap *joint_map) {
223  // A sequence node gets converted to an ordinary EggGroup, we only apply the
224  // appropriate switch attributes to turn it into a sequence
225  EggGroup *egg_group = new EggGroup(node->get_name());
226  egg_parent->add_child(egg_group);
227  apply_node_properties(egg_group, node);
228 
229  // turn it into a sequence with the right frame-rate
230  egg_group->set_switch_flag(true);
231  egg_group->set_switch_fps(node->get_frame_rate());
232 
233  int num_children = node->get_num_children();
234 
235  for (int i = 0; i < num_children; i++) {
236  PandaNode *child = node->get_child(i);
237 
238  // Convert just this one node to an EggGroup.
239  PT(EggGroup) next_group = new EggGroup;
240  convert_node(WorkingNodePath(node_path, child), next_group, has_decal, joint_map);
241 
242  egg_group->add_child(next_group.p());
243  }
244 
245 }
246 
247 /**
248  * Converts the indicated SwitchNode to the corresponding Egg constructs.
249  */
250 void EggSaver::
251 convert_switch_node(SwitchNode *node, const WorkingNodePath &node_path,
252  EggGroupNode *egg_parent, bool has_decal,
253  CharacterJointMap *joint_map) {
254  // A sequence node gets converted to an ordinary EggGroup, we only apply the
255  // appropriate switch attributes to turn it into a sequence
256  EggGroup *egg_group = new EggGroup(node->get_name());
257  egg_parent->add_child(egg_group);
258  apply_node_properties(egg_group, node);
259 
260  // turn it into a switch..
261  egg_group->set_switch_flag(true);
262 
263  int num_children = node->get_num_children();
264 
265  for (int i = 0; i < num_children; i++) {
266  PandaNode *child = node->get_child(i);
267 
268  // Convert just this one node to an EggGroup.
269  PT(EggGroup) next_group = new EggGroup;
270  convert_node(WorkingNodePath(node_path, child), next_group, has_decal, joint_map);
271 
272  egg_group->add_child(next_group.p());
273  }
274 }
275 
276 /**
277  * Converts the indicated AnimationGroupNodes to the corresponding Egg
278  * constructs.
279  */
280 EggGroupNode * EggSaver::convert_animGroup_node(AnimGroup *animGroup, double fps ) {
281  int num_children = animGroup->get_num_children();
282 
283  EggGroupNode *eggNode = nullptr;
284  if (animGroup->is_of_type(AnimBundle::get_class_type())) {
285  EggTable *eggTable = new EggTable(animGroup->get_name());
286  eggTable ->set_table_type(EggTable::TT_bundle);
287  eggNode = eggTable;
288  } else if (animGroup->is_of_type(AnimGroup::get_class_type())) {
289  EggTable *eggTable = new EggTable(animGroup->get_name());
290  eggTable ->set_table_type(EggTable::TT_table);
291  eggNode = eggTable;
292  }
293 
294  if (animGroup->is_of_type(AnimChannelMatrixXfmTable::get_class_type())) {
295  AnimChannelMatrixXfmTable *xmfTable = DCAST(AnimChannelMatrixXfmTable, animGroup);
296  EggXfmSAnim *egg_anim = new EggXfmSAnim("xform");
297  egg_anim->set_fps(fps);
298  for (int i = 0; i < num_matrix_components; i++) {
299  string componentName(1, matrix_component_letters[i]);
300  char table_id = matrix_component_letters[i];
301  CPTA_stdfloat table = xmfTable->get_table(table_id);
302 
303  if (xmfTable->has_table(table_id)) {
304  for (unsigned int j = 0; j < table.size(); j++) {
305  egg_anim->add_component_data(componentName, table[(int)j]);
306  }
307  }
308  }
309  eggNode->add_child(egg_anim);
310  }
311  for (int i = 0; i < num_children; i++) {
312  AnimGroup *animChild = animGroup->get_child(i);
313  EggGroupNode *eggChildNode = convert_animGroup_node(animChild, fps);
314  if (eggChildNode!=nullptr) {
315  nassertr(eggNode!=nullptr, nullptr);
316  eggNode->add_child(eggChildNode);
317  }
318  }
319  return eggNode;
320 }
321 
322 /**
323  * Converts the indicated AnimNode to the corresponding Egg constructs.
324  */
325 void EggSaver::
326 convert_anim_node(AnimBundleNode *node, const WorkingNodePath &node_path,
327  EggGroupNode *egg_parent, bool has_decal) {
328 
329  // A sequence node gets converted to an ordinary EggGroup, we only apply the
330  // appropriate switch attributes to turn it into a sequence
331  EggTable *eggTable = new EggTable();
332  // egg_parent->add_child(eggTable);
333  _data->add_child(eggTable);
334 
335  AnimBundle *animBundle = node->get_bundle();
336  // turn it into a switch.. egg_group->set_switch_flag(true);
337 
338  EggGroupNode *eggAnimation = convert_animGroup_node(animBundle, animBundle->get_base_frame_rate());
339  eggTable->add_child(eggAnimation);
340 }
341 
342 /**
343  * Converts the indicated Character Bundle to the corresponding Egg joints
344  * structure.
345  */
346 void EggSaver::
347 convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, CharacterJointMap *joint_map) {
348  convert_character_bundle(bundleNode, egg_parent, joint_map, nullptr);
349 }
350 
351 /**
352  * Converts the indicated Character Bundle to the corresponding Egg joints
353  * structure.
354  */
355 void EggSaver::
356 convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent,
357  CharacterJointMap *joint_map, const CharacterJoint *parent_joint) {
358  int num_children = bundleNode->get_num_children();
359 
360  const CharacterJoint *character_joint = nullptr;
361 
362  EggGroupNode *joint_group = egg_parent;
363  if (bundleNode->is_of_type(CharacterJoint::get_class_type())) {
364  character_joint = DCAST(CharacterJoint, bundleNode);
365 
366  EggGroup *joint = new EggGroup(bundleNode->get_name());
367  joint->set_group_type(EggGroup::GT_joint);
368 
369  // The default_value originally passed to the CharacterJoint is what is used
370  // for skinning. However, the _default_value can be changed after joint
371  // construction (such as via a <DefaultPose>), so we can't just pull the
372  // current _default_value.
373  //
374  // We have to instead work back from the _initial_net_transform_inverse,
375  // which is computed at construction time from the original default_value:
376  //
377  // _net_transform = default_value * parent_joint->_net_transform;
378  // _initial_net_transform_inverse = invert(_net_transform);
379  //
380  // So we should be able to reconstruct the original default_value like so:
381  //
382  // default_value = invert(_initial_net_transform_inverse)
383  // * parent_joint->_initial_net_transform_inverse;
384  //
385  LMatrix4d net_transform = invert(LCAST(double, character_joint->_initial_net_transform_inverse));
386  if (parent_joint != nullptr) {
387  if (parent_joint->_initial_net_transform_inverse != character_joint->_initial_net_transform_inverse) {
388  LMatrix4d parent_inverse = LCAST(double, parent_joint->_initial_net_transform_inverse);
389  joint->add_matrix4(net_transform * parent_inverse);
390  }
391  } else if (!net_transform.is_identity()) {
392  joint->add_matrix4(net_transform);
393  }
394 
395  // The joint's _default_value, if different, goes into a <DefaultPose>.
396  LMatrix4d default_pose = LCAST(double, character_joint->_default_value);
397  if (default_pose != joint->get_transform3d()) {
398  EggTransform transform;
399  transform.add_matrix4(LCAST(double, default_pose));
400  joint->set_default_pose(transform);
401  }
402 
403  joint_group = joint;
404  egg_parent->add_child(joint_group);
405  if (joint_map != nullptr) {
406  CharacterJointMap::iterator mi = joint_map->find(character_joint);
407  if (mi != joint_map->end()) {
408  pvector<pair<EggVertex*,PN_stdfloat> > &joint_vertices = (*mi).second;
409  pvector<pair<EggVertex*,PN_stdfloat> >::const_iterator vi;
410  for (vi = joint_vertices.begin(); vi != joint_vertices.end(); ++vi) {
411  joint->set_vertex_membership((*vi).first, (*vi).second);
412  }
413  }
414  }
415  }
416 
417  for (int i = 0; i < num_children ; i++) {
418  PartGroup *partGroup= bundleNode->get_child(i);
419  convert_character_bundle(partGroup, joint_group, joint_map, character_joint);
420  }
421 
422 }
423 
424 /**
425  * Converts the indicated Character to the corresponding Egg constructs.
426  */
427 void EggSaver::
428 convert_character_node(Character *node, const WorkingNodePath &node_path,
429  EggGroupNode *egg_parent, bool has_decal) {
430 
431  // A sequence node gets converted to an ordinary EggGroup, we only apply the
432  // appropriate switch attributes to turn it into a sequence.
433  // We have to use DT_structured since it is the only mode that preserves the
434  // node hierarchy, including LODNodes and CollisionNodes that may be under
435  // this Character node.
436  EggGroup *egg_group = new EggGroup(node->get_name());
437  egg_group->set_dart_type(EggGroup::DT_structured);
438  egg_parent->add_child(egg_group);
439  apply_node_properties(egg_group, node);
440 
441  CharacterJointMap joint_map;
442  recurse_nodes(node_path, egg_group, has_decal, &joint_map);
443 
444  // turn it into a switch.. egg_group->set_switch_flag(true);
445 
446  int num_bundles = node->get_num_bundles();
447  for (int i = 0; i < num_bundles; ++i) {
448  PartBundle *bundle = node->get_bundle(i);
449  convert_character_bundle(bundle, egg_group, &joint_map);
450  }
451 }
452 
453 
454 /**
455  * Converts the indicated CollisionNode to the corresponding Egg constructs.
456  */
457 void EggSaver::
458 convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
459  EggGroupNode *egg_parent, bool has_decal,
460  CharacterJointMap *joint_map) {
461  // A sequence node gets converted to an ordinary EggGroup, we only apply the
462  // appropriate switch attributes to turn it into a sequence
463  EggGroup *egg_group = new EggGroup(node->get_name());
464  egg_parent->add_child(egg_group);
465  apply_node_properties(egg_group, node, false);
466 
467  // Set the collision masks, if present.
468  CollideMask from_mask = node->get_from_collide_mask();
469  CollideMask into_mask = node->get_into_collide_mask();
470  if (from_mask != CollisionNode::get_default_collide_mask() ||
472  if (from_mask == into_mask) {
473  egg_group->set_collide_mask(into_mask);
474  } else {
475  egg_group->set_from_collide_mask(from_mask);
476  egg_group->set_into_collide_mask(into_mask);
477  }
478  }
479 
480  // turn it into a collision node
481  egg_group->set_collide_flags(EggGroup::CF_descend);
482 
483  NodePath np = node_path.get_node_path();
484  CPT(TransformState) net_transform = np.get_net_transform();
485  LMatrix4 net_mat = net_transform->get_mat();
486  LMatrix4 inv = LCAST(PN_stdfloat, egg_parent->get_vertex_frame_inv());
487  net_mat = net_mat * inv;
488 
489  int num_solids = node->get_num_solids();
490 
491  if (num_solids > 0) {
492  // create vertex pool for collisions
493  EggVertexPool *cvpool = new EggVertexPool("vpool-collision");
494  egg_group->add_child(cvpool);
495 
496  // traverse solids
497  for (int i = 0; i < num_solids; i++) {
498  CPT(CollisionSolid) child = node->get_solid(i);
499  int flags = EggGroup::CF_descend;
500 
501  if (!child->is_tangible()) {
502  flags |= EggGroup::CF_intangible;
503  }
504 
505  if (child->has_effective_normal() &&
506  child->get_effective_normal() == LVector3::up()) {
507  flags |= EggGroup::CF_level;
508  }
509 
510  if (child->is_of_type(CollisionPolygon::get_class_type())) {
511  egg_group->set_cs_type(EggGroup::CST_polyset);
512  egg_group->set_collide_flags(flags);
513 
514  EggPolygon *egg_poly = new EggPolygon;
515  egg_group->add_child(egg_poly);
516 
517  CPT(CollisionPolygon) poly = DCAST(CollisionPolygon, child);
518  int num_points = poly->get_num_points();
519  for (int j = 0; j < num_points; j++) {
520  EggVertex egg_vert;
521  egg_vert.set_pos(LCAST(double, poly->get_point(j) * net_mat));
522  egg_vert.set_normal(LCAST(double, poly->get_normal() * net_mat));
523 
524  EggVertex *new_egg_vert = cvpool->create_unique_vertex(egg_vert);
525  egg_poly->add_vertex(new_egg_vert);
526  }
527 
528  } else if (child->is_of_type(CollisionSphere::get_class_type())) {
529  CPT(CollisionSphere) sphere = DCAST(CollisionSphere, child);
530  LPoint3 center = sphere->get_center();
531  PN_stdfloat radius = sphere->get_radius();
532 
533  EggGroup *egg_sphere;
534  if (num_solids == 1) {
535  egg_sphere = egg_group;
536  } else {
537  egg_sphere = new EggGroup;
538  egg_group->add_child(egg_sphere);
539  }
540 
541  if (child->is_of_type(CollisionInvSphere::get_class_type())) {
542  egg_sphere->set_cs_type(EggGroup::CST_inv_sphere);
543  } else {
544  egg_sphere->set_cs_type(EggGroup::CST_sphere);
545  }
546  egg_sphere->set_collide_flags(flags);
547 
548  EggVertex ev1, ev2, ev3, ev4;
549  ev1.set_pos(LCAST(double, (center + LVector3(radius, 0, 0)) * net_mat));
550  ev2.set_pos(LCAST(double, (center + LVector3(0, radius, 0)) * net_mat));
551  ev3.set_pos(LCAST(double, (center + LVector3(-radius, 0, 0)) * net_mat));
552  ev4.set_pos(LCAST(double, (center + LVector3(0, -radius, 0)) * net_mat));
553 
554  EggPolygon *egg_poly = new EggPolygon;
555  egg_sphere->add_child(egg_poly);
556 
557  egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
558  egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
559  egg_poly->add_vertex(cvpool->create_unique_vertex(ev3));
560  egg_poly->add_vertex(cvpool->create_unique_vertex(ev4));
561 
562  } else if (child->is_of_type(CollisionPlane::get_class_type())) {
563  LPlane plane = DCAST(CollisionPlane, child)->get_plane();
564  LPoint3 origin = plane.get_point();
565  LVector3 normal = plane.get_normal();
566 
567  // Get an arbitrary vector on the plane by taking the cross product
568  // with any vector, as long as it is different.
569  LVector3 vec1;
570  if (std::fabs(normal[2]) > std::fabs(normal[1])) {
571  vec1 = normal.cross(LVector3(0, 1, 0));
572  } else {
573  vec1 = normal.cross(LVector3(0, 0, 1));
574  }
575 
576  // Find a second vector perpendicular to the two.
577  LVector3 vec2 = normal.cross(vec1);
578 
579  EggGroup *egg_plane;
580  if (num_solids == 1) {
581  egg_plane = egg_group;
582  } else {
583  egg_plane = new EggGroup;
584  egg_group->add_child(egg_plane);
585  }
586  egg_plane->set_cs_type(EggGroup::CST_plane);
587  egg_plane->set_collide_flags(flags);
588 
589  EggVertex ev0, ev1, ev2;
590  ev0.set_pos(LCAST(double, origin * net_mat));
591  ev1.set_pos(LCAST(double, (origin + vec1) * net_mat));
592  ev2.set_pos(LCAST(double, (origin + vec2) * net_mat));
593 
594  EggPolygon *egg_poly = new EggPolygon;
595  egg_plane->add_child(egg_poly);
596 
597  egg_poly->add_vertex(cvpool->create_unique_vertex(ev0));
598  egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
599  egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
600 
601  } else if (child->is_of_type(CollisionBox::get_class_type())) {
602  CPT(CollisionBox) box = DCAST(CollisionBox, child);
603  LPoint3 min_point = box->get_min();
604  LPoint3 max_point = box->get_max();
605 
606  EggGroup *egg_box;
607  if (num_solids == 1) {
608  egg_box = egg_group;
609  } else {
610  egg_box = new EggGroup;
611  egg_group->add_child(egg_box);
612  }
613  egg_box->set_cs_type(EggGroup::CST_box);
614  egg_box->set_collide_flags(flags);
615 
616  // Just add the min and max points.
617  EggVertex ev0, ev1;
618  ev0.set_pos(LCAST(double, min_point * net_mat));
619  ev1.set_pos(LCAST(double, max_point * net_mat));
620 
621  EggLine *egg_poly = new EggLine;
622  egg_box->add_child(egg_poly);
623 
624  egg_poly->add_vertex(cvpool->create_unique_vertex(ev0));
625  egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
626 
627  } else if (child->is_of_type(CollisionCapsule::get_class_type())) {
628  CPT(CollisionCapsule) capsule = DCAST(CollisionCapsule, child);
629  LPoint3 point_a = capsule->get_point_a();
630  LPoint3 point_b = capsule->get_point_b();
631  LPoint3 centroid = (point_a + point_b) * 0.5f;
632 
633  // Also get an arbitrary vector perpendicular to the capsule.
634  LVector3 axis = point_b - point_a;
635  LVector3 sideways;
636  if (std::fabs(axis[2]) > std::fabs(axis[1])) {
637  sideways = axis.cross(LVector3(0, 1, 0));
638  } else {
639  sideways = axis.cross(LVector3(0, 0, 1));
640  }
641  sideways.normalize();
642  sideways *= capsule->get_radius();
643  LVector3 extend = axis.normalized() * capsule->get_radius();
644 
645  EggGroup *egg_capsule;
646  if (num_solids == 1) {
647  egg_capsule = egg_group;
648  } else {
649  egg_capsule = new EggGroup;
650  egg_group->add_child(egg_capsule);
651  }
652  egg_capsule->set_cs_type(EggGroup::CST_tube);
653  egg_capsule->set_collide_flags(flags);
654 
655  // Add two points for the endcaps, and then two points around the
656  // centroid to indicate the radius.
657  EggVertex ev0, ev1, ev2, ev3;
658  ev0.set_pos(LCAST(double, (point_a - extend) * net_mat));
659  ev1.set_pos(LCAST(double, (centroid + sideways) * net_mat));
660  ev2.set_pos(LCAST(double, (point_b + extend) * net_mat));
661  ev3.set_pos(LCAST(double, (centroid - sideways) * net_mat));
662 
663  EggPolygon *egg_poly = new EggPolygon;
664  egg_capsule->add_child(egg_poly);
665 
666  egg_poly->add_vertex(cvpool->create_unique_vertex(ev0));
667  egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
668  egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
669  egg_poly->add_vertex(cvpool->create_unique_vertex(ev3));
670 
671  } else {
672  nout << "Encountered unknown collision solid type " << child->get_type() << "\n";
673  }
674  }
675  }
676 
677  // recurse over children - hm. do I need to do this?
678  recurse_nodes(node_path, egg_group, has_decal, joint_map);
679 }
680 
681 /**
682  * Converts a GeomNode to the corresponding egg structures.
683  */
684 void EggSaver::
685 convert_geom_node(GeomNode *node, const WorkingNodePath &node_path,
686  EggGroupNode *egg_parent, bool has_decal, CharacterJointMap *joint_map) {
687  PT(EggGroup) egg_group = new EggGroup(node->get_name());
688  bool fancy_attributes = apply_node_properties(egg_group, node);
689 
690  if (node->get_effects()->has_decal()) {
691  has_decal = true;
692  }
693 
694  if (has_decal) {
695  egg_group->set_decal_flag(true);
696  }
697 
698  if (fancy_attributes || has_decal || !node->get_name().empty()) {
699  // If we have any fancy attributes on the node, or if we're making decal
700  // geometry, we have to make a special node to hold the geometry (normally
701  // it would just appear within its parent).
702  egg_parent->add_child(egg_group.p());
703  egg_parent = egg_group;
704  }
705 
706  NodePath np = node_path.get_node_path();
707  CPT(RenderState) net_state = np.get_net_state();
708  CPT(TransformState) net_transform = np.get_net_transform();
709  LMatrix4 net_mat = net_transform->get_mat();
710  LMatrix4 inv = LCAST(PN_stdfloat, egg_parent->get_vertex_frame_inv());
711  net_mat = net_mat * inv;
712 
713  // Now get out all the various kinds of geometry.
714  int num_geoms = node->get_num_geoms();
715  for (int i = 0; i < num_geoms; ++i) {
716  CPT(RenderState) geom_state = node->get_geom_state(i);
717  CPT(RenderState) geom_net_state = net_state->compose(geom_state);
718 
719  // If there is only one Geom, and the node has no state, apply the state
720  // attributes from the Geom to the group instead, so that we don't end up
721  // duplicating it for a lot of primitives.
722  if (num_geoms == 1 && node->get_num_children() == 0 && egg_parent == egg_group &&
723  !geom_state->is_empty() && node->get_state()->is_empty()) {
724  apply_state_properties(egg_group, geom_state);
725  geom_state = RenderState::make_empty();
726  }
727 
728  const Geom *geom = node->get_geom(i);
729  int num_primitives = geom->get_num_primitives();
730  for (int j = 0; j < num_primitives; ++j) {
731  const GeomPrimitive *primitive = geom->get_primitive(j);
732  CPT(GeomPrimitive) simple = primitive->decompose();
733  CPT(GeomVertexData) vdata = geom->get_vertex_data();
734  // vdata = vdata->animate_vertices(true, Thread::get_current_thread());
735  convert_primitive(vdata, simple, geom_state, geom_net_state,
736  net_mat, egg_parent, joint_map);
737  }
738  }
739 
740  recurse_nodes(node_path, egg_parent, has_decal, joint_map);
741 }
742 
743 /**
744  *
745  */
746 void EggSaver::
747 convert_primitive(const GeomVertexData *vertex_data,
748  const GeomPrimitive *primitive,
749  const RenderState *geom_state, const RenderState *net_state,
750  const LMatrix4 &net_mat, EggGroupNode *egg_parent,
751  CharacterJointMap *joint_map) {
752  GeomVertexReader reader(vertex_data);
753  const GeomVertexFormat *format = vertex_data->get_format();
754 
755  // Make a zygote that will be duplicated for each primitive.
756  PT(EggPrimitive) egg_prim;
757  if (primitive->is_of_type(GeomTriangles::get_class_type())) {
758  egg_prim = new EggPolygon();
759  } else if (primitive->is_of_type(GeomPatches::get_class_type())) {
760  egg_prim = new EggPatch();
761  } else if (primitive->is_of_type(GeomPoints::get_class_type())) {
762  egg_prim = new EggPoint();
763  } else if (primitive->is_of_type(GeomLines::get_class_type())) {
764  egg_prim = new EggLine();
765  } else {
766  // Huh, an unknown geometry type.
767  return;
768  }
769 
770  // Apply render attributes.
771  apply_state_properties(egg_prim, geom_state);
772 
773  // Check for a color scale.
774  LVecBase4 color_scale(1.0f, 1.0f, 1.0f, 1.0f);
775  const ColorScaleAttrib *csa;
776  if (net_state->get_attrib(csa)) {
777  color_scale = csa->get_scale();
778  }
779 
780  // Check for a color override.
781  bool has_color_override = false;
782  bool has_color_off = false;
783  LColor color_override;
784  const ColorAttrib *ca;
785  if (net_state->get_attrib(ca)) {
786  if (ca->get_color_type() == ColorAttrib::T_flat) {
787  has_color_override = true;
788  color_override = ca->get_color();
789  color_override.set(color_override[0] * color_scale[0],
790  color_override[1] * color_scale[1],
791  color_override[2] * color_scale[2],
792  color_override[3] * color_scale[3]);
793 
794  } else if (ca->get_color_type() == ColorAttrib::T_off) {
795  has_color_off = true;
796  }
797  }
798 
799  // Check for a material.
800  EggMaterial *egg_mat = nullptr;
801  const MaterialAttrib *ma;
802  if (net_state->get_attrib(ma)) {
803  egg_mat = get_egg_material(ma->get_material());
804  if (egg_mat != nullptr) {
805  egg_prim->set_material(egg_mat);
806  }
807  }
808 
809  // Check for a texture.
810  const TextureAttrib *ta;
811  if (net_state->get_attrib(ta)) {
812  for (size_t i = 0; i < ta->get_num_on_stages(); ++i) {
813  TextureStage *tex_stage = ta->get_on_stage(i);
814 
815  EggTexture *egg_tex = get_egg_texture(ta->get_on_texture(tex_stage));
816  if (egg_tex != nullptr) {
817  switch (tex_stage->get_mode()) {
818  case TextureStage::M_modulate:
819  if (has_color_off == true && i == 0) {
820  egg_tex->set_env_type(EggTexture::ET_replace);
821  } else {
822  egg_tex->set_env_type(EggTexture::ET_modulate);
823  }
824  break;
825  case TextureStage::M_decal:
826  egg_tex->set_env_type(EggTexture::ET_decal);
827  break;
828  case TextureStage::M_blend:
829  egg_tex->set_env_type(EggTexture::ET_blend);
830  break;
831  case TextureStage::M_replace:
832  egg_tex->set_env_type(EggTexture::ET_replace);
833  break;
834  case TextureStage::M_add:
835  egg_tex->set_env_type(EggTexture::ET_add);
836  break;
837  case TextureStage::M_blend_color_scale:
838  egg_tex->set_env_type(EggTexture::ET_blend_color_scale);
839  break;
840  case TextureStage::M_modulate_glow:
841  egg_tex->set_env_type(EggTexture::ET_modulate_glow);
842  break;
843  case TextureStage::M_modulate_gloss:
844  egg_tex->set_env_type(EggTexture::ET_modulate_gloss);
845  break;
846  case TextureStage::M_normal:
847  egg_tex->set_env_type(EggTexture::ET_normal);
848  break;
849  case TextureStage::M_normal_height:
850  egg_tex->set_env_type(EggTexture::ET_normal_height);
851  break;
852  case TextureStage::M_glow:
853  egg_tex->set_env_type(EggTexture::ET_glow);
854  break;
855  case TextureStage::M_gloss:
856  egg_tex->set_env_type(EggTexture::ET_gloss);
857  break;
858  case TextureStage::M_height:
859  egg_tex->set_env_type(EggTexture::ET_height);
860  break;
861  case TextureStage::M_selector:
862  egg_tex->set_env_type(EggTexture::ET_selector);
863  break;
864  case TextureStage::M_normal_gloss:
865  egg_tex->set_env_type(EggTexture::ET_normal_gloss);
866  break;
867  default:
868  break;
869  }
870 
871  const InternalName *name = tex_stage->get_texcoord_name();
872  if (name != nullptr && name != InternalName::get_texcoord()) {
873  egg_tex->set_uv_name(name->get_basename());
874  }
875 
876  egg_prim->add_texture(egg_tex);
877  }
878  }
879  }
880 
881  // Check the backface flag.
882  const CullFaceAttrib *cfa;
883  if (net_state->get_attrib(cfa)) {
884  if (cfa->get_effective_mode() == CullFaceAttrib::M_cull_none) {
885  egg_prim->set_bface_flag(true);
886  }
887  }
888 
889  // Check for line thickness and such.
890  const RenderModeAttrib *rma;
891  if (net_state->get_attrib(rma)) {
892  if (egg_prim->is_of_type(EggPoint::get_class_type())) {
893  EggPoint *egg_point = (EggPoint *)egg_prim.p();
894  egg_point->set_thick(rma->get_thickness());
895  egg_point->set_perspective(rma->get_perspective());
896 
897  } else if (egg_prim->is_of_type(EggLine::get_class_type())) {
898  EggLine *egg_line = (EggLine *)egg_prim.p();
899  egg_line->set_thick(rma->get_thickness());
900  }
901  }
902 
903  CPT(TransformBlendTable) transformBlendTable = vertex_data->get_transform_blend_table();
904 
905  int num_primitives = primitive->get_num_primitives();
906  int num_vertices = primitive->get_num_vertices_per_primitive();
907 
908  for (int i = 0; i < num_primitives; ++i) {
909  PT(EggPrimitive) egg_child = egg_prim->make_copy();
910  egg_parent->add_child(egg_child);
911 
912  for (int j = 0; j < num_vertices; j++) {
913  EggVertex egg_vert;
914 
915  // Get per-vertex properties.
916  reader.set_row(primitive->get_vertex(i * num_vertices + j));
917 
918  reader.set_column(InternalName::get_vertex());
919  LVertex vertex = reader.get_data3();
920  egg_vert.set_pos(LCAST(double, vertex * net_mat));
921 
922  if (vertex_data->has_column(InternalName::get_normal())) {
923  reader.set_column(InternalName::get_normal());
924  LNormal normal = reader.get_data3();
925  egg_vert.set_normal(LCAST(double, normal * net_mat));
926  }
927  if (has_color_override) {
928  egg_vert.set_color(color_override);
929 
930  } else if (!has_color_off) {
931  LColor color(1.0f, 1.0f, 1.0f, 1.0f);
932  if (vertex_data->has_column(InternalName::get_color())) {
933  reader.set_column(InternalName::get_color());
934  color = reader.get_data4();
935  }
936  egg_vert.set_color(LColor(color[0] * color_scale[0],
937  color[1] * color_scale[1],
938  color[2] * color_scale[2],
939  color[3] * color_scale[3]));
940  }
941 
942  for (size_t ti = 0; ti < format->get_num_texcoords(); ++ti) {
943  const InternalName *texcoord_name = format->get_texcoord(ti);
944  reader.set_column(texcoord_name);
945  LTexCoord uv = reader.get_data2();
946  if (texcoord_name == InternalName::get_texcoord()) {
947  egg_vert.set_uv(LCAST(double, uv));
948  } else {
949  egg_vert.set_uv(texcoord_name->get_basename(), LCAST(double, uv));
950  }
951  }
952 
953  EggVertex *new_egg_vert = _vpool->create_unique_vertex(egg_vert);
954 
955  if (vertex_data->has_column(InternalName::get_transform_blend()) &&
956  joint_map != nullptr && transformBlendTable != nullptr) {
957  reader.set_column(InternalName::get_transform_blend());
958  int idx = reader.get_data1i();
959  const TransformBlend &blend = transformBlendTable->get_blend(idx);
960  int num_weights = blend.get_num_transforms();
961  for (int k = 0; k < num_weights; ++k) {
962  PN_stdfloat weight = blend.get_weight(k);
963  if (weight!=0) {
964  const VertexTransform *vertex_transform = blend.get_transform(k);
965  if (vertex_transform->is_of_type(JointVertexTransform::get_class_type())) {
966  const JointVertexTransform *joint_vertex_transform = DCAST(const JointVertexTransform, vertex_transform);
967 
968  CharacterJointMap::iterator mi = joint_map->find(joint_vertex_transform->get_joint());
969  if (mi == joint_map->end()) {
970  mi = joint_map->insert(CharacterJointMap::value_type(joint_vertex_transform->get_joint(), pvector<pair<EggVertex*,PN_stdfloat> >())).first;
971  }
972  pvector<pair<EggVertex*,PN_stdfloat> > &joint_vertices = (*mi).second;
973  joint_vertices.push_back(pair<EggVertex*,PN_stdfloat>(new_egg_vert, weight));
974  }
975  }
976  }
977  }
978 
979  egg_child->add_vertex(new_egg_vert);
980  }
981  }
982 }
983 
984 /**
985  * Converts all the children of the indicated node.
986  */
987 void EggSaver::
988 recurse_nodes(const WorkingNodePath &node_path, EggGroupNode *egg_parent,
989  bool has_decal, CharacterJointMap *joint_map) {
990  PandaNode *node = node_path.node();
991  int num_children = node->get_num_children();
992 
993  for (int i = 0; i < num_children; i++) {
994  PandaNode *child = node->get_child(i);
995  convert_node(WorkingNodePath(node_path, child), egg_parent, has_decal, joint_map);
996  }
997 }
998 
999 /**
1000  * Applies any special properties that might be stored on the node, like
1001  * billboarding. Returns true if any were applied, false otherwise.
1002  */
1003 bool EggSaver::
1004 apply_node_properties(EggGroup *egg_group, PandaNode *node, bool allow_backstage) {
1005  bool any_applied = false;
1006 
1007  if (node->is_overall_hidden() && allow_backstage) {
1008  // This node is hidden. We'll go ahead and convert it, but we'll put in
1009  // the "backstage" flag to mean it's not real geometry. unless the caller
1010  // wants to keep it (by setting allow_backstage to false)
1011  egg_group->add_object_type("backstage");
1012  }
1013 
1014  if (node->has_tags()) {
1015  if (apply_tags(egg_group, node)) {
1016  any_applied = true;
1017  }
1018  }
1019 
1020  if (node->is_of_type(ModelNode::get_class_type())) {
1021  ModelNode *model_node = DCAST(ModelNode, node);
1022  switch (model_node->get_preserve_transform()) {
1023  case ModelNode::PT_none:
1024  egg_group->set_model_flag(true);
1025  break;
1026 
1027  case ModelNode::PT_drop_node:
1028  break;
1029 
1030  case ModelNode::PT_net:
1031  egg_group->set_dcs_type(EggGroup::DC_net);
1032  break;
1033 
1034  case ModelNode::PT_local:
1035  egg_group->set_dcs_type(EggGroup::DC_local);
1036  break;
1037 
1038  case ModelNode::PT_no_touch:
1039  egg_group->set_dcs_type(EggGroup::DC_no_touch);
1040  break;
1041  }
1042  }
1043 
1044  if (node->is_of_type(UvScrollNode::get_class_type())) {
1045  const UvScrollNode *scroll_node = (const UvScrollNode *)node;
1046  egg_group->set_scroll_u(scroll_node->get_u_speed());
1047  egg_group->set_scroll_v(scroll_node->get_v_speed());
1048  egg_group->set_scroll_w(scroll_node->get_w_speed());
1049  egg_group->set_scroll_r(scroll_node->get_r_speed());
1050  }
1051 
1052  const RenderEffects *effects = node->get_effects();
1053  const RenderEffect *effect = effects->get_effect(BillboardEffect::get_class_type());
1054  if (effect != nullptr) {
1055  const BillboardEffect *bbe = DCAST(BillboardEffect, effect);
1056  if (bbe->get_axial_rotate()) {
1057  egg_group->set_billboard_type(EggGroup::BT_axis);
1058  any_applied = true;
1059 
1060  } else if (bbe->get_eye_relative()) {
1061  egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
1062  any_applied = true;
1063 
1064  } else {
1065  egg_group->set_billboard_type(EggGroup::BT_point_world_relative);
1066  any_applied = true;
1067  }
1068  }
1069 
1070  const TransformState *transform = node->get_transform();
1071  if (!transform->is_identity()) {
1072  if (transform->has_components()) {
1073  // If the transform can be represented componentwise, we prefer storing
1074  // it that way in the egg file.
1075  const LVecBase3 &scale = transform->get_scale();
1076  const LQuaternion &quat = transform->get_quat();
1077  const LVecBase3 &pos = transform->get_pos();
1078  if (!scale.almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
1079  egg_group->add_scale3d(LCAST(double, scale));
1080  }
1081  if (!quat.is_identity()) {
1082  egg_group->add_rotate3d(LCAST(double, quat));
1083  }
1084  if (!pos.almost_equal(LVecBase3::zero())) {
1085  egg_group->add_translate3d(LCAST(double, pos));
1086  }
1087 
1088  } else if (transform->has_mat()) {
1089  // Otherwise, we store the raw matrix.
1090  const LMatrix4 &mat = transform->get_mat();
1091  egg_group->set_transform3d(LCAST(double, mat));
1092  }
1093  any_applied = true;
1094  }
1095 
1096  const RenderState *state = node->get_state();
1097  if (apply_state_properties(egg_group, state)) {
1098  return true;
1099  }
1100 
1101  return any_applied;
1102 }
1103 
1104 /**
1105  * Applies any special render state settings on the primitive or group.
1106  * Returns true if any were applied, false otherwise.
1107  */
1108 bool EggSaver::
1109 apply_state_properties(EggRenderMode *egg_render_mode, const RenderState *state) {
1110  if (state->is_empty()) {
1111  return false;
1112  }
1113 
1114  bool any_applied = false;
1115 
1116  // Check the transparency mode.
1117  const TransparencyAttrib *tra;
1118  if (state->get_attrib(tra)) {
1119  EggRenderMode::AlphaMode tex_trans = EggRenderMode::AM_unspecified;
1120  switch (tra->get_mode()) {
1121  case TransparencyAttrib::M_none:
1122  tex_trans = EggRenderMode::AM_off;
1123  break;
1124  case TransparencyAttrib::M_alpha:
1125  tex_trans = EggRenderMode::AM_blend;
1126  break;
1127  case TransparencyAttrib::M_premultiplied_alpha:
1128  tex_trans = EggRenderMode::AM_premultiplied;
1129  break;
1130  case TransparencyAttrib::M_multisample:
1131  tex_trans = EggRenderMode::AM_ms;
1132  break;
1133  case TransparencyAttrib::M_multisample_mask:
1134  tex_trans = EggRenderMode::AM_ms_mask;
1135  break;
1136  case TransparencyAttrib::M_binary:
1137  tex_trans = EggRenderMode::AM_binary;
1138  break;
1139  case TransparencyAttrib::M_dual:
1140  tex_trans = EggRenderMode::AM_dual;
1141  break;
1142  default: // intentional fall-through
1143  break;
1144  }
1145  egg_render_mode->set_alpha_mode(tex_trans);
1146  }
1147 
1148  const DepthWriteAttrib *dwa;
1149  if (state->get_attrib(dwa)) {
1150  if (dwa->get_mode() != DepthWriteAttrib::M_off) {
1151  egg_render_mode->set_depth_write_mode(EggRenderMode::DWM_on);
1152 
1153  } else if (egg_render_mode->get_alpha_mode() == EggRenderMode::AM_blend) {
1154  // AM_blend_no_occlude is like AM_blend but also implies DWM_off.
1155  egg_render_mode->set_alpha_mode(EggRenderMode::AM_blend_no_occlude);
1156 
1157  } else {
1158  egg_render_mode->set_depth_write_mode(EggRenderMode::DWM_off);
1159  }
1160  any_applied = true;
1161  }
1162 
1163  const DepthTestAttrib *dta;
1164  if (state->get_attrib(dta)) {
1165  RenderAttrib::PandaCompareFunc mode = dta->get_mode();
1166  if (mode == DepthTestAttrib::M_none || mode == DepthTestAttrib::M_always) {
1167  egg_render_mode->set_depth_test_mode(EggRenderMode::DTM_off);
1168  } else {
1169  egg_render_mode->set_depth_test_mode(EggRenderMode::DTM_on);
1170  }
1171  any_applied = true;
1172  }
1173 
1174  const DepthOffsetAttrib *doa;
1175  if (state->get_attrib(doa)) {
1176  egg_render_mode->set_depth_offset(doa->get_offset());
1177  any_applied = true;
1178  }
1179 
1180  const CullBinAttrib *cba;
1181  if (state->get_attrib(cba)) {
1182  egg_render_mode->set_bin(cba->get_bin_name());
1183  egg_render_mode->set_draw_order(cba->get_draw_order());
1184  any_applied = true;
1185  }
1186 
1187  return any_applied;
1188 }
1189 
1190 /**
1191  * Applies string tags to the egg file. Returns true if any were applied,
1192  * false otherwise.
1193  */
1194 bool EggSaver::
1195 apply_tags(EggGroup *egg_group, PandaNode *node) {
1196  std::ostringstream strm;
1197  char delimiter = '\n';
1198  string delimiter_str(1, delimiter);
1199  node->list_tags(strm, delimiter_str);
1200 
1201  string data = strm.str();
1202  if (data.empty()) {
1203  return false;
1204  }
1205 
1206  bool any_applied = false;
1207 
1208  size_t p = 0;
1209  size_t q = data.find(delimiter);
1210  while (q != string::npos) {
1211  string tag = data.substr(p, q);
1212  if (apply_tag(egg_group, node, tag)) {
1213  any_applied = true;
1214  }
1215  p = q + 1;
1216  q = data.find(delimiter, p);
1217  }
1218 
1219  string tag = data.substr(p);
1220  if (apply_tag(egg_group, node, tag)) {
1221  any_applied = true;
1222  }
1223 
1224  return any_applied;
1225 }
1226 
1227 /**
1228  * Applies the named string tags to the egg file.
1229  */
1230 bool EggSaver::
1231 apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag) {
1232  if (!node->has_tag(tag)) {
1233  return false;
1234  }
1235 
1236  string value = node->get_tag(tag);
1237  egg_group->set_tag(tag, value);
1238  return true;
1239 }
1240 
1241 /**
1242  * Returns an EggMaterial pointer that corresponds to the indicated Material.
1243  */
1244 EggMaterial *EggSaver::
1245 get_egg_material(Material *mat) {
1246  if (mat != nullptr) {
1247  EggMaterial temp(mat->get_name());
1248  if (mat->has_base_color()) {
1249  temp.set_base(mat->get_base_color());
1250  }
1251 
1252  if (mat->has_ambient()) {
1253  temp.set_amb(mat->get_ambient());
1254  }
1255 
1256  if (mat->has_diffuse()) {
1257  temp.set_diff(mat->get_diffuse());
1258  }
1259 
1260  if (mat->has_specular()) {
1261  temp.set_spec(mat->get_specular());
1262  }
1263 
1264  if (mat->has_emission()) {
1265  temp.set_emit(mat->get_emission());
1266  }
1267 
1268  if (mat->has_roughness()) {
1269  temp.set_roughness(mat->get_roughness());
1270  } else {
1271  temp.set_shininess(mat->get_shininess());
1272  }
1273 
1274  if (mat->has_metallic()) {
1275  temp.set_metallic(mat->get_metallic());
1276  }
1277 
1278  if (mat->has_refractive_index()) {
1279  temp.set_ior(mat->get_refractive_index());
1280  }
1281 
1282  temp.set_local(mat->get_local());
1283 
1284  return _materials.create_unique_material(temp, ~EggMaterial::E_mref_name);
1285  }
1286 
1287  return nullptr;
1288 }
1289 
1290 /**
1291  * Returns an EggTexture pointer that corresponds to the indicated Texture.
1292  */
1293 EggTexture *EggSaver::
1294 get_egg_texture(Texture *tex) {
1295  if (tex != nullptr) {
1296  if (tex->has_filename()) {
1297  Filename filename = tex->get_filename();
1298  EggTexture temp(filename.get_basename_wo_extension(), filename);
1299  if (tex->has_alpha_filename()) {
1300  Filename alpha = tex->get_alpha_filename();
1301  temp.set_alpha_filename(alpha);
1302  }
1303 
1304  switch (tex->get_minfilter()) {
1305  case SamplerState::FT_nearest:
1306  temp.set_minfilter(EggTexture::FT_nearest);
1307  break;
1308  case SamplerState::FT_linear:
1309  temp.set_minfilter(EggTexture::FT_linear);
1310  break;
1311  case SamplerState::FT_nearest_mipmap_nearest:
1312  temp.set_minfilter(EggTexture::FT_nearest_mipmap_nearest);
1313  break;
1314  case SamplerState::FT_linear_mipmap_nearest:
1315  temp.set_minfilter(EggTexture::FT_linear_mipmap_nearest);
1316  break;
1317  case SamplerState::FT_nearest_mipmap_linear:
1318  temp.set_minfilter(EggTexture::FT_nearest_mipmap_linear);
1319  break;
1320  case SamplerState::FT_linear_mipmap_linear:
1321  temp.set_minfilter(EggTexture::FT_linear_mipmap_linear);
1322  break;
1323 
1324  default:
1325  break;
1326  }
1327 
1328  switch (tex->get_magfilter()) {
1329  case SamplerState::FT_nearest:
1330  temp.set_magfilter(EggTexture::FT_nearest);
1331  break;
1332  case SamplerState::FT_linear:
1333  temp.set_magfilter(EggTexture::FT_linear);
1334  break;
1335 
1336  default:
1337  break;
1338  }
1339 
1340  switch (tex->get_wrap_u()) {
1341  case SamplerState::WM_clamp:
1342  temp.set_wrap_u(EggTexture::WM_clamp);
1343  break;
1344  case SamplerState::WM_repeat:
1345  temp.set_wrap_u(EggTexture::WM_repeat);
1346  break;
1347 
1348  default:
1349  // There are some new wrap options on Texture that aren't yet
1350  // supported in egg.
1351  break;
1352  }
1353 
1354  switch (tex->get_wrap_v()) {
1355  case SamplerState::WM_clamp:
1356  temp.set_wrap_v(EggTexture::WM_clamp);
1357  break;
1358  case SamplerState::WM_repeat:
1359  temp.set_wrap_v(EggTexture::WM_repeat);
1360  break;
1361 
1362  default:
1363  // There are some new wrap options on Texture that aren't yet
1364  // supported in egg.
1365  break;
1366  }
1367 
1368  switch (tex->get_format()) {
1369  case Texture::F_red:
1370  temp.set_format(EggTexture::F_red);
1371  break;
1372  case Texture::F_green:
1373  temp.set_format(EggTexture::F_green);
1374  break;
1375  case Texture::F_blue:
1376  temp.set_format(EggTexture::F_blue);
1377  break;
1378  case Texture::F_alpha:
1379  temp.set_format(EggTexture::F_alpha);
1380  break;
1381  case Texture::F_rgb:
1382  temp.set_format(EggTexture::F_rgb);
1383  break;
1384  case Texture::F_rgb5:
1385  temp.set_format(EggTexture::F_rgb5);
1386  break;
1387  case Texture::F_rgb8:
1388  temp.set_format(EggTexture::F_rgb8);
1389  break;
1390  case Texture::F_rgb12:
1391  temp.set_format(EggTexture::F_rgb12);
1392  break;
1393  case Texture::F_rgb332:
1394  temp.set_format(EggTexture::F_rgb332);
1395  break;
1396  case Texture::F_rgba:
1397  temp.set_format(EggTexture::F_rgba);
1398  break;
1399  case Texture::F_rgbm:
1400  temp.set_format(EggTexture::F_rgbm);
1401  break;
1402  case Texture::F_rgba4:
1403  temp.set_format(EggTexture::F_rgba4);
1404  break;
1405  case Texture::F_rgba5:
1406  temp.set_format(EggTexture::F_rgba5);
1407  break;
1408  case Texture::F_rgba8:
1409  temp.set_format(EggTexture::F_rgba8);
1410  break;
1411  case Texture::F_rgba12:
1412  temp.set_format(EggTexture::F_rgba12);
1413  break;
1414  case Texture::F_luminance:
1415  temp.set_format(EggTexture::F_luminance);
1416  break;
1417  case Texture::F_luminance_alpha:
1418  temp.set_format(EggTexture::F_luminance_alpha);
1419  break;
1420  case Texture::F_luminance_alphamask:
1421  temp.set_format(EggTexture::F_luminance_alphamask);
1422  break;
1423  case Texture::F_srgb:
1424  temp.set_format(EggTexture::F_srgb);
1425  break;
1426  case Texture::F_srgb_alpha:
1427  temp.set_format(EggTexture::F_srgb_alpha);
1428  break;
1429  default:
1430  break;
1431  }
1432 
1433  return _textures.create_unique_texture(temp, ~EggTexture::E_tref_name);
1434  }
1435  }
1436 
1437  return nullptr;
1438 }
LODNode::get_out
get_out
Returns the "out" distance of the indicated switch range.
Definition: lodNode.h:61
PartGroup::get_num_children
get_num_children
Returns the number of child nodes of the group.
Definition: partGroup.h:72
Geom
A container for geometry primitives.
Definition: geom.h:54
CollisionNode::get_default_collide_mask
get_default_collide_mask
Returns the default into_collide_mask assigned to new CollisionNodes.
Definition: collisionNode.h:79
eggSaver.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TransformState::is_identity
bool is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.
Definition: transformState.I:197
DepthTestAttrib::get_mode
get_mode
Returns the depth write mode.
Definition: depthTestAttrib.h:37
BillboardEffect::get_axial_rotate
bool get_axial_rotate() const
Returns true if this billboard rotates only around the axis of the up vector, or false if it rotates ...
Definition: billboardEffect.I:85
DepthTestAttrib
Enables or disables writing to the depth buffer.
Definition: depthTestAttrib.h:26
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggTable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::is_geom_node
virtual bool is_geom_node() const
A simple downcast check.
Definition: pandaNode.cxx:2062
EggRenderMode::set_depth_offset
void set_depth_offset(int bias)
Sets the "depth-offset" flag associated with this object.
Definition: eggRenderMode.I:108
eggLine.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ModelNode::get_preserve_transform
PreserveTransform get_preserve_transform() const
Returns the current setting of the preserve_transform flag.
Definition: modelNode.I:61
PartGroup
This is the base class for PartRoot and MovingPart.
Definition: partGroup.h:43
animChannelMatrixXfmTable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pandaNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderEffects
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition: renderEffects.h:41
TransformState::get_quat
get_quat
Returns the rotation component of the transform as a quaternion.
Definition: transformState.h:152
RenderModeAttrib::get_thickness
get_thickness
Returns the line width or point thickness.
Definition: renderModeAttrib.h:70
EggPatch
A single "patch", a special primitive to be rendered only with a tessellation shader.
Definition: eggPatch.h:25
AnimBundle
This is the root of an AnimChannel hierarchy.
Definition: animBundle.h:29
eggVertexPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
sequenceNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggXfmSAnim.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPrimitive::get_num_vertices_per_primitive
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices,...
Definition: geomPrimitive.h:194
billboardEffect.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggPrimitive.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
LODNode::get_in
get_in
Returns the "in" distance of the indicated switch range.
Definition: lodNode.h:59
RenderEffects::get_effect
const RenderEffect * get_effect(size_t n) const
Returns the nth effect in the state.
Definition: renderEffects.I:111
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggPoint.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::get_wrap_v
get_wrap_v
Returns the wrap mode of the texture in the V direction.
Definition: texture.h:374
TransformBlend
This defines a single entry in a TransformBlendTable.
Definition: transformBlend.h:32
CollisionCapsule
This implements a solid consisting of a cylinder with hemispherical endcaps, also known as a capsule ...
Definition: collisionCapsule.h:27
TransformBlend::get_num_transforms
get_num_transforms
Returns the number of transforms stored in the blend object.
Definition: transformBlend.h:63
AnimChannelMatrixXfmTable::has_table
has_table
Returns true if the indicated subtable has been assigned.
Definition: animChannelMatrixXfmTable.h:62
AnimGroup::get_child
get_child
Returns the nth child of the group.
Definition: animGroup.h:45
GeomVertexFormat::get_num_texcoords
get_num_texcoords
Returns the number of columns within the format that represent texture coordinates.
Definition: geomVertexFormat.h:114
RenderEffect
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:48
collisionBox.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
JointVertexTransform::get_joint
const CharacterJoint * get_joint() const
Returns the joint for which this object returns the transform.
Definition: jointVertexTransform.I:18
Texture::get_format
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
Definition: texture.h:362
geomVertexReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TransparencyAttrib
This controls the enabling of transparency.
Definition: transparencyAttrib.h:31
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
collisionSphere.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LODNode
A Level-of-Detail node.
Definition: lodNode.h:28
EggTransform::get_transform3d
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
Definition: eggTransform.I:212
eggSAnimData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexData::get_format
get_format
Returns a pointer to the GeomVertexFormat structure that defines this data.
Definition: geomVertexData.h:98
EggNode::get_vertex_frame_inv
const LMatrix4d & get_vertex_frame_inv() const
Returns the inverse of the matrix returned by get_vertex_frame().
Definition: eggNode.I:135
DepthWriteAttrib::get_mode
get_mode
Returns the depth write mode.
Definition: depthWriteAttrib.h:43
EggTexture::set_uv_name
set_uv_name
Specifies the named set of texture coordinates that this texture will use when it is applied to geome...
Definition: eggTexture.h:340
TextureAttrib::get_on_texture
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
Definition: textureAttrib.h:69
Material
Defines the way an object appears in the presence of lighting.
Definition: material.h:43
TransformState::has_mat
bool has_mat() const
Returns true if the transform can be described as a matrix.
Definition: transformState.I:368
Filename::get_basename_wo_extension
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:386
EggTable
This corresponds to a.
Definition: eggTable.h:27
Texture::get_filename
get_filename
Returns the filename that has been set.
Definition: texture.h:312
bamCacheRecord.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
modelNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggMaterialCollection::create_unique_material
EggMaterial * create_unique_material(const EggMaterial &copy, int eq)
Creates a new material if there is not already one equivalent (according to eq, see EggMaterial::is_e...
Definition: eggMaterialCollection.cxx:364
GeomVertexFormat::get_texcoord
get_texcoord
Returns the name of the nth texcoord column.
Definition: geomVertexFormat.h:114
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
uvScrollNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggMaterial
Definition: eggMaterial.h:26
BillboardEffect::get_eye_relative
bool get_eye_relative() const
Returns true if this billboard interprets the up vector relative to the camera, or false if it is rel...
Definition: billboardEffect.I:76
TextureStage::get_mode
get_mode
Return the mode of this stage.
Definition: textureStage.h:196
eggMaterial.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
ConstPointerToArray
Similar to PointerToArray, except that its contents may not be modified.
Definition: pointerToArray.h:250
BillboardEffect
Indicates that geometry at this node should automatically rotate to face the camera,...
Definition: billboardEffect.h:27
GeomVertexReader
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
Definition: geomVertexReader.h:47
EggGroup::set_default_pose
set_default_pose
Replaces the initial pose transform.
Definition: eggGroup.h:320
TransformState::get_mat
get_mat
Returns the matrix that describes the transform.
Definition: transformState.h:156
InternalName::get_basename
get_basename
Return the name represented by just this particular InternalName object, ignoring its parents names.
Definition: internalName.h:62
BitMask< uint32_t, 32 >
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
geomLines.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggTexture.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
collisionNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:49
GeomPrimitive::get_vertex
get_vertex
Returns the ith vertex index in the table.
Definition: geomPrimitive.h:99
CharacterJoint
This represents one joint of the character's animation, containing an animating transform matrix.
Definition: characterJoint.h:32
AnimBundle::get_base_frame_rate
get_base_frame_rate
Returns the ideal number of frames per second of the animation, when it is running at normal speed.
Definition: animBundle.h:41
EggRenderMode::get_alpha_mode
AlphaMode get_alpha_mode() const
Returns the alpha mode that was set, or AM_unspecified if nothing was set.
Definition: eggRenderMode.I:98
WorkingNodePath::get_node_path
get_node_path
Constructs and returns an actual NodePath that represents the same path we have just traversed.
Definition: workingNodePath.h:60
GeomNode::get_num_geoms
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
Texture::get_wrap_u
get_wrap_u
Returns the wrap mode of the texture in the U direction.
Definition: texture.h:370
PandaNode::list_tags
void list_tags(std::ostream &out, const std::string &separator="\n") const
Writes a list of all the tag keys assigned to the node to the indicated stream.
Definition: pandaNode.cxx:1277
bamFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggGroup::set_vertex_membership
void set_vertex_membership(EggVertex *vert, double membership)
Explicitly sets the net membership of the indicated vertex in this group to the given value.
Definition: eggGroup.cxx:692
materialAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
EggLine
A line segment, or a series of connected line segments, defined by a <Line> entry.
Definition: eggLine.h:25
CollisionSphere
A spherical collision volume or object.
Definition: collisionSphere.h:25
DepthWriteAttrib
Enables or disables writing to the depth buffer.
Definition: depthWriteAttrib.h:26
CullFaceAttrib::get_effective_mode
get_effective_mode
Returns the effective culling mode.
Definition: cullFaceAttrib.h:50
DepthOffsetAttrib::get_offset
get_offset
Returns the depth offset represented by this attrib.
Definition: depthOffsetAttrib.h:64
EggXfmSAnim
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
Definition: eggXfmSAnim.h:28
EggData
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
switchNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AnimGroup::get_num_children
get_num_children
Returns the number of child nodes of the group.
Definition: animGroup.h:45
depthOffsetAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AnimChannelMatrixXfmTable
An animation channel that issues a matrix each frame, read from a table such as might have been read ...
Definition: animChannelMatrixXfmTable.h:31
EggVertex::set_uv
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
Definition: eggVertex.I:193
TransformState::get_scale
get_scale
Returns the scale component of the transform.
Definition: transformState.h:154
transformState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
transformTable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::get_magfilter
get_magfilter
Returns the filter mode of the texture for magnification.
Definition: texture.h:389
colorScaleAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WorkingNodePath
This is a class designed to support low-overhead traversals of the complete scene graph,...
Definition: workingNodePath.h:39
CullBinAttrib::get_bin_name
get_bin_name
Returns the name of the bin this attribute specifies.
Definition: cullBinAttrib.h:39
EggPolygon
A single polygon.
Definition: eggPolygon.h:24
CollisionPolygon
Definition: collisionPolygon.h:29
renderEffects.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
character.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggVertex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPrimitive::get_num_primitives
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
Definition: geomPrimitive.I:126
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
WorkingNodePath::node
PandaNode * node() const
Returns the node traversed to so far.
Definition: workingNodePath.I:89
lodNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderModeAttrib
Specifies how polygons are to be drawn.
Definition: renderModeAttrib.h:27
eggPatch.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
transparencyAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
depthWriteAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::get_child
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
Texture::has_alpha_filename
has_alpha_filename
Returns true if the alpha_filename has been set and is available.
Definition: texture.h:318
cullFaceAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomTriangles.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggTransform::add_scale3d
void add_scale3d(const LVecBase3d &scale)
Appends a possibly non-uniform scale to the current transform.
Definition: eggTransform.cxx:167
MaterialAttrib
Indicates which, if any, material should be applied to geometry.
Definition: materialAttrib.h:27
GeomVertexData::has_column
bool has_column(const InternalName *name) const
Returns true if the data has the named column, false otherwise.
Definition: geomVertexData.I:52
TransparencyAttrib::get_mode
get_mode
Returns the transparency mode.
Definition: transparencyAttrib.h:54
EggPrimitive::add_vertex
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
Definition: eggPrimitive.cxx:654
SequenceNode
A node that automatically cycles through rendering each one of its children according to its frame ra...
Definition: sequenceNode.h:27
collisionCapsule.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geom.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullBinAttrib
Assigns geometry to a particular bin by name.
Definition: cullBinAttrib.h:27
EggTransform::set_transform3d
void set_transform3d(const LMatrix4d &mat)
Sets the overall transform as a 4x4 matrix.
Definition: eggTransform.I:188
TransformBlend::get_transform
get_transform
Returns the nth transform stored in the blend object.
Definition: transformBlend.h:63
AnimGroup
This is the base class for AnimChannel and AnimBundle.
Definition: animGroup.h:33
eggRenderMode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LODNode::get_center
get_center
Returns the center of the LOD.
Definition: lodNode.h:83
Texture::get_alpha_filename
get_alpha_filename
Returns the alpha_filename that has been set.
Definition: texture.h:318
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
ModelNode
This node is placed at key points within the scene graph to indicate the roots of "models": subtrees ...
Definition: modelNode.h:31
TextureAttrib::get_num_on_stages
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
Definition: textureAttrib.h:55
CollisionSolid
The abstract base class for all things that can collide with other things in the world,...
Definition: collisionSolid.h:45
ColorAttrib::get_color_type
get_color_type
Returns the type of color specified by this ColorAttrib.
Definition: colorAttrib.h:46
collisionInvSphere.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomPatches.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MaterialAttrib::get_material
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
Definition: materialAttrib.h:40
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
depthTestAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
workingNodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::has_filename
has_filename
Returns true if the filename has been set and is available.
Definition: texture.h:312
EggTextureCollection::create_unique_texture
EggTexture * create_unique_texture(const EggTexture &copy, int eq)
Creates a new texture if there is not already one equivalent (according to eq, see EggTexture::is_equ...
Definition: eggTextureCollection.cxx:432
SwitchNode
A node that renders only one of its children, according to the user's indication.
Definition: switchNode.h:25
EggTransform::add_matrix4
void add_matrix4(const LMatrix4d &mat)
Appends an arbitrary 4x4 matrix to the current transform.
Definition: eggTransform.I:132
textureStage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
textureAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartGroup::get_child
get_child
Returns the nth child of the group.
Definition: partGroup.h:72
TransformState::has_components
bool has_components() const
Returns true if the transform can be described by separate pos, hpr, and scale components.
Definition: transformState.I:246
ColorScaleAttrib
Applies a scale to colors in the scene graph and on vertices.
Definition: colorScaleAttrib.h:27
CollisionPlane
Definition: collisionPlane.h:27
NodePath::get_mat
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
Definition: nodePath.I:776
TextureAttrib::get_on_stage
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Definition: textureAttrib.h:55
EggRenderMode::set_depth_test_mode
void set_depth_test_mode(DepthTestMode mode)
Specifies whether this geometry should be tested against the depth buffer when it is drawn (assuming ...
Definition: eggRenderMode.I:46
TextureStage::get_texcoord_name
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:192
AnimBundleNode
This is a node that contains a pointer to an AnimBundle.
Definition: animBundleNode.h:29
EggTexture
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:30
EggSaver::add_subgraph
void add_subgraph(PandaNode *root)
Adds the scene graph rooted at the indicated node (but without the node itself) to the accumulated eg...
Definition: eggSaver.cxx:117
TransformState::get_pos
get_pos
Returns the pos component of the transform.
Definition: transformState.h:150
CollisionNode::get_from_collide_mask
get_from_collide_mask
Returns the current "from" CollideMask.
Definition: collisionNode.h:59
geomPoints.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggXfmSAnim::add_component_data
void add_component_data(const std::string &component_name, double value)
Adds a new row to the named component (one of matrix_component_letters) of the table.
Definition: eggXfmSAnim.cxx:556
TransformBlend::get_blend
void get_blend(LMatrix4 &result, Thread *current_thread) const
Returns the current value of the blend, based on the current value of all of the nested transform obj...
Definition: transformBlend.I:196
EggVertexPool::create_unique_vertex
EggVertex * create_unique_vertex(const EggVertex &copy)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
Definition: eggVertexPool.cxx:472
EggVertexPool
A collection of vertices.
Definition: eggVertexPool.h:41
GeomNode::get_geom_state
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Definition: geomNode.h:75
TransformBlend::get_weight
get_weight
Returns the weight associated with the indicated transform, or 0 if there is no entry for the transfo...
Definition: transformBlend.h:71
collisionPolygon.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullBinAttrib::get_draw_order
get_draw_order
Returns the draw order this attribute specifies.
Definition: cullBinAttrib.h:40
CollisionBox
A cuboid collision volume or object.
Definition: collisionBox.h:27
JointVertexTransform
This is a specialization on VertexTransform that returns the transform necessary to move vertices as ...
Definition: jointVertexTransform.h:33
RenderState::is_empty
bool is_empty() const
Returns true if the state is empty, false otherwise.
Definition: renderState.I:27
EggRenderMode::set_draw_order
void set_draw_order(int order)
Sets the "draw-order" flag associated with this object.
Definition: eggRenderMode.I:149
EggRenderMode::set_depth_write_mode
void set_depth_write_mode(DepthWriteMode mode)
Specifies whether writes should be made to the depth buffer (assuming the rendering backend provides ...
Definition: eggRenderMode.I:27
UvScrollNode
This node is placed at key points within the scene graph to animate uvs.
Definition: uvScrollNode.h:26
characterJoint.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggTransform::add_translate3d
void add_translate3d(const LVector3d &translate)
Appends a 3-d translation operation to the current transform.
Definition: eggTransform.cxx:71
animBundleNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::get_num_children
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
DepthOffsetAttrib
This is a special kind of attribute that instructs the graphics driver to apply an offset or bias to ...
Definition: depthOffsetAttrib.h:50
EggGroup
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
TextureAttrib
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
EggGroupNode::add_child
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
Definition: eggGroupNode.cxx:243
EggVertex::set_pos
void set_pos(double pos)
Sets the vertex position.
Definition: eggVertex.I:42
ColorAttrib
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
EggRenderMode::set_alpha_mode
void set_alpha_mode(AlphaMode mode)
Specifies precisely how the transparency for this geometry should be achieved, or if it should be use...
Definition: eggRenderMode.I:89
EggSwitchConditionDistance
A SwitchCondition that switches the levels-of-detail based on distance from the camera's eyepoint.
Definition: eggSwitchCondition.h:61
PandaNode::is_overall_hidden
is_overall_hidden
Returns true if the node has been hidden to all cameras by clearing its overall bit.
Definition: pandaNode.h:248
EggPoint
A single point, or a collection of points as defined by a single <PointLight> entry.
Definition: eggPoint.h:25
EggTransform::add_rotate3d
void add_rotate3d(double angle, const LVector3d &axis)
Appends a 3-d rotation about an arbitrary axis to the current transform.
Definition: eggTransform.cxx:131
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
EggGroup::set_tag
void set_tag(const std::string &key, const std::string &value)
Associates a user-defined value with a user-defined key which is stored on the node.
Definition: eggGroup.I:720
EggRenderMode::set_bin
void set_bin(const std::string &bin)
Sets the "bin" string for this particular object.
Definition: eggRenderMode.I:189
RenderModeAttrib::get_perspective
get_perspective
Returns the perspective flag.
Definition: renderModeAttrib.h:71
TransformBlendTable
This structure collects together the different combinations of transforms and blend amounts used by a...
Definition: transformBlendTable.h:45
eggXfmAnimData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
collisionPlane.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggGroup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggSaver::add_node
void add_node(PandaNode *node)
Adds the scene graph rooted at the indicated node to the accumulated egg data within this object.
Definition: eggSaver.cxx:97
CollisionNode::get_into_collide_mask
get_into_collide_mask
Returns the current "into" CollideMask.
Definition: collisionNode.h:61
EggRenderMode
This class stores miscellaneous rendering properties that is associated with geometry,...
Definition: eggRenderMode.h:31
CullFaceAttrib
Indicates which faces should be culled based on their vertex ordering.
Definition: cullFaceAttrib.h:26
VertexTransform
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
Definition: vertexTransform.h:35
CollisionNode
A node in the scene graph that can hold any number of CollisionSolids.
Definition: collisionNode.h:30
ColorScaleAttrib::get_scale
get_scale
Returns the scale to be applied to colors.
Definition: colorScaleAttrib.h:47
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PartBundle
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
AnimChannelMatrixXfmTable::get_table
get_table
Returns a pointer to the indicated subtable's data, if it exists, or NULL if it does not.
Definition: animChannelMatrixXfmTable.h:62
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
GeomPrimitive
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
ColorAttrib::get_color
get_color
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
Definition: colorAttrib.h:47
eggPolygon.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullBinAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Character
An animated character, with skeleton-morph animation and either soft- skinned or hard-skinned vertice...
Definition: character.h:38
Texture::get_minfilter
get_minfilter
Returns the filter mode of the texture for minification.
Definition: texture.h:383
LODNode::get_num_switches
get_num_switches
Returns the number of switch ranges added to the LODNode.
Definition: lodNode.h:59
EggTransform
This represents the <Transform> entry of a group or texture node: a list of component transform opera...
Definition: eggTransform.h:29