Browse Source

add egg2bam

David Rose 24 năm trước cách đây
mục cha
commit
5e4ce3a6df
3 tập tin đã thay đổi với 600 bổ sung0 xóa
  1. 20 0
      pandatool/src/bam/Sources.pp
  2. 496 0
      pandatool/src/bam/bamToEgg.cxx
  3. 84 0
      pandatool/src/bam/bamToEgg.h

+ 20 - 0
pandatool/src/bam/Sources.pp

@@ -36,3 +36,23 @@
 
 #end bin_target
 
+
+#begin bin_target
+  #define TARGET bam2egg
+  #define LOCAL_LIBS \
+    eggbase progbase
+  #define OTHER_LIBS \
+    parametrics:c collide:c chan:c char:c switchnode:c \
+    cull:c loader:c egg:c sgraphutil:c sgattrib:c \
+    sgraph:c pnmimagetypes:c \
+    graph:c putil:c linmath:c express:c panda:m pandaexpress:m \
+    interrogatedb:c dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
+
+  #define UNIX_SYS_LIBS \
+    m
+
+  #define SOURCES \
+    bamToEgg.cxx bamToEgg.h
+
+#end bin_target
+

+ 496 - 0
pandatool/src/bam/bamToEgg.cxx

@@ -0,0 +1,496 @@
+// Filename: bamToEgg.cxx
+// Created by:  drose (25Jun01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "bamToEgg.h"
+
+#include "node.h"
+#include "LODNode.h"
+#include "geomNode.h"
+#include "geom.h"
+#include "geomTri.h"
+#include "renderRelation.h"
+#include "string_utils.h"
+#include "bamFile.h"
+#include "eggGroup.h"
+#include "eggVertexPool.h"
+#include "eggVertex.h"
+#include "eggPrimitive.h"
+#include "eggPolygon.h"
+#include "eggTexture.h"
+#include "eggMaterial.h"
+#include "arcChain.h"
+#include "allTransitionsWrapper.h"
+#include "wrt.h"
+#include "transformTransition.h"
+#include "texMatrixTransition.h"
+#include "colorMatrixTransition.h"
+#include "alphaTransformTransition.h"
+#include "textureTransition.h"
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+BamToEgg::GeomState::
+GeomState() {
+  _mat = LMatrix4f::ident_mat();
+  _tex_mat = LMatrix4f::ident_mat();
+  _color_mat = LMatrix4f::ident_mat();
+  _alpha_scale = 1.0;
+  _alpha_offset = 0.0;
+  _tex = (Texture *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::get_net_state
+//       Access: Public
+//  Description: Gets the accumulated state of the indicated node (and
+//               its corresponding ArcChain) into the GeomState.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+get_net_state(Node *node, ArcChain &chain) {
+  AllTransitionsWrapper atw;
+
+  wrt(node, chain.begin(), chain.end(),
+      (Node *)NULL,
+      atw, RenderRelation::get_class_type());
+
+  // Check for transform space.
+  const TransformTransition *tt;
+  if (get_transition_into(tt, atw)) {
+    _mat = tt->get_matrix();
+  }
+
+  // Check for texture matrix.
+  const TexMatrixTransition *tmt;
+  if (get_transition_into(tmt, atw)) {
+    _tex_mat = tmt->get_matrix();
+  }
+
+  // Check for color matrix.
+  const ColorMatrixTransition *cmt;
+  if (get_transition_into(cmt, atw)) {
+    _color_mat = cmt->get_matrix();
+  }
+
+  // Check for alpha scale/offset.
+  const AlphaTransformTransition *att;
+  if (get_transition_into(att, atw)) {
+    _alpha_scale = att->get_scale();
+    _alpha_offset = att->get_offset();
+  }
+
+  // Check for texture.
+  const TextureTransition *txt;
+  if (get_transition_into(txt, atw)) {
+    if (txt->is_on()) {
+      _tex = txt->get_texture();
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::apply
+//       Access: Public
+//  Description: Applies the state to the indicated EggPrimitive, as
+//               appropriate.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+apply(EggPrimitive *egg_prim, 
+      EggTextureCollection &textures,
+      EggMaterialCollection &materials) {
+  if (_tex != (Texture *)NULL) {
+    if (_tex->has_name()) {
+      EggTexture temp("", _tex->get_name());
+      if (_tex->has_alpha_name()) {
+        temp.set_alpha_file(_tex->get_alpha_name());
+      }
+
+      EggTexture *egg_tex = 
+        textures.create_unique_texture(temp, ~EggTexture::E_tref_name);
+      egg_prim->set_texture(egg_tex);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::apply_vertex
+//       Access: Public
+//  Description: Applies the indicated vertex coordinate to the given
+//               EggVertex, after modifying it according to the
+//               current state.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+apply_vertex(EggVertex &egg_vert, const Vertexf &vertex) {
+  LPoint3f transformed = vertex * _mat;
+  egg_vert.set_pos(LCAST(double, transformed));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::apply_normal
+//       Access: Public
+//  Description: Applies the indicated vertex normal to the given
+//               EggVertex, after modifying it according to the
+//               current state.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+apply_normal(EggVertex &egg_vert, const Normalf &normal) {
+  LPoint3f transformed = normal * _mat;
+  egg_vert.set_normal(LCAST(double, transformed));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::apply_uv
+//       Access: Public
+//  Description: Applies the indicated vertex UV to the given
+//               EggVertex, after modifying it according to the
+//               current state.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+apply_uv(EggVertex &egg_vert, const TexCoordf &uv) {
+  LVecBase4f v4(uv[0], uv[1], 0.0, 1.0);
+  v4 = v4 * _tex_mat;
+  egg_vert.set_uv(LCAST(double, uv));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::GeomState::apply_color
+//       Access: Public
+//  Description: Applies the indicated vertex color to the given
+//               EggVertex, after modifying it according to the
+//               current state.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::GeomState::
+apply_color(EggVertex &egg_vert, const Colorf &color) {
+  LPoint3f temp(color[0], color[1], color[2]);
+  temp = temp * _color_mat;
+  float alpha = (color[3] * _alpha_scale) +
+    _alpha_offset;
+  
+  Colorf transformed(temp[0], temp[1], temp[2], alpha);
+  egg_vert.set_color(transformed);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BamToEgg::
+BamToEgg() :
+  SomethingToEgg("Bam", ".bam")
+{
+  add_texture_path_options();
+  add_rel_dir_options();
+  add_search_path_options(false);
+
+  set_program_description
+    ("This program converts native Panda Bam files to egg.  The conversion "
+     "is somewhat incomplete; running egg2bam followed by bam2egg should not "
+     " be expected to yield the same egg file you started with.");
+
+  redescribe_option
+    ("cs",
+     "Specify the coordinate system of the input " + _format_name +
+     " file.  By default, this is taken from the Configrc file, which "
+     "is currently " + format_string(default_coordinate_system) + ".");
+
+  _coordinate_system = default_coordinate_system;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+run() {
+  BamFile bam_file;
+
+  if (!bam_file.open_read(_input_filename)) {
+    nout << "Unable to read " << _input_filename << "\n";
+    exit(1);
+  }
+
+  nout << _input_filename << " : Bam version "
+       << bam_file.get_file_major_ver() << "." 
+       << bam_file.get_file_minor_ver() << "\n";
+
+  typedef pvector<TypedWritable *> Objects;
+  Objects objects;
+  TypedWritable *object = bam_file.read_object();
+  while (object != (TypedWritable *)NULL || !bam_file.is_eof()) {
+    if (object != (TypedWritable *)NULL) {
+      objects.push_back(object);
+    }
+    object = bam_file.read_object();
+  }
+  bam_file.resolve();
+  bam_file.close();
+
+  _data.set_coordinate_system(_coordinate_system);
+  _vpool = new EggVertexPool("vpool");
+  _data.add_child(_vpool);
+
+  if (objects.size() == 1 && objects[0]->is_of_type(Node::get_class_type())) {
+    Node *node = DCAST(Node, objects[0]);
+    ArcChain chain(node);
+    convert_node(node, chain, &_data);
+
+  } else {
+    nout << "File does not contain a scene graph.\n";
+    exit(1);
+  }
+
+  // Remove the vertex pool if it has no vertices.
+  if (_vpool->empty()) {
+    _data.remove_child(_vpool);
+  }
+
+  write_egg_file();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::convert_node
+//       Access: Private
+//  Description: Converts the indicated node to the corresponding Egg
+//               constructs, by first determining what kind of node it
+//               is.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+convert_node(Node *node, ArcChain &chain, EggGroupNode *egg_parent) {
+  if (node->is_of_type(LODNode::get_class_type())) {
+    convert_lod_node(DCAST(LODNode, node), chain, egg_parent);
+
+  } else if (node->is_of_type(GeomNode::get_class_type())) {
+    convert_geom_node(DCAST(GeomNode, node), chain, egg_parent);
+
+  } else {
+    // Just a generic node.  See if it has a name, at least.
+    string name;
+    if (node->is_of_type(NamedNode::get_class_type())) {
+      name = DCAST(NamedNode, node)->get_name();
+    }
+    
+    EggGroup *egg_group = new EggGroup(name);
+    egg_parent->add_child(egg_group);
+    
+    recurse_nodes(node, chain, egg_group);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::convert_lod_node
+//       Access: Private
+//  Description: Converts the indicated LODNode to the corresponding
+//               Egg constructs.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+convert_lod_node(LODNode *node, ArcChain &chain, EggGroupNode *egg_parent) {
+  // An LOD node gets converted to an ordinary EggGroup, but we apply
+  // the appropriate switch conditions to each of our children.
+  string name = node->get_name();
+
+  EggGroup *egg_group = new EggGroup(name);
+  egg_parent->add_child(egg_group);
+
+  int num_children = node->get_num_children(RenderRelation::get_class_type());
+  int num_switches = node->get_num_switches();
+
+  num_children = min(num_children, num_switches);
+
+  for (int i = 0; i < num_children; i++) {
+    NodeRelation *arc = 
+      node->get_child(RenderRelation::get_class_type(), i);
+    ArcChain next_chain(chain);
+    next_chain.push_back(arc);
+
+    // Convert just this one node to an EggGroup.
+    PT(EggGroup) next_group = new EggGroup;
+    convert_node(arc->get_child(), next_chain, next_group);
+
+    if (next_group->size() == 1) {
+      // If we have exactly one child, and that child is an EggGroup,
+      // collapse.
+      EggNode *child_node = *next_group->begin();
+      if (child_node->is_of_type(EggGroup::get_class_type())) {
+        PT(EggGroup) child = DCAST(EggGroup, child_node);
+        next_group->remove_child(child.p());
+        next_group = child;
+      }
+    }
+
+    // Now set up the switching properties appropriately.
+    float in = node->get_in(i);
+    float out = node->get_out(i);
+    LPoint3f center = node->_lod._center;
+    EggSwitchConditionDistance dist(in, out, LCAST(double, center));
+    next_group->set_lod(dist);
+    egg_group->add_child(next_group.p());
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::convert_geom_node
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+convert_geom_node(GeomNode *node, ArcChain &chain, EggGroupNode *egg_parent) {
+  // Get the state associated with this GeomNode.
+  GeomState state;
+  state.get_net_state(node, chain);
+
+  // Now get out all the various kinds of geometry.
+  int num_geoms = node->get_num_geoms();
+  for (int i = 0; i < num_geoms; i++) {
+    dDrawable *drawable = node->get_geom(i);
+    if (drawable->is_of_type(Geom::get_class_type())) {
+      // Explode the Geom before we try to deal with it.  That way, we
+      // don't have to know about tristrips or whatnot.
+      Geom *geom = DCAST(Geom, drawable);
+      PT(Geom) exploded = geom->explode();
+
+      // Now determine what kind of Geom we've got.  Chances are good
+      // it's triangles.
+      if (exploded->is_of_type(GeomTri::get_class_type())) {
+        convert_geom_tri(DCAST(GeomTri, exploded), state, egg_parent);
+      }
+    }
+  }
+  
+  recurse_nodes(node, chain, egg_parent);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::convert_geom
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+convert_geom_tri(GeomTri *geom, BamToEgg::GeomState &state, EggGroupNode *egg_parent) {
+  int nprims = geom->get_num_prims();
+  Geom::VertexIterator vi = geom->make_vertex_iterator();
+  Geom::NormalIterator ni = geom->make_normal_iterator();
+  Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
+  Geom::ColorIterator ci = geom->make_color_iterator();
+
+  GeomBindType vb = geom->get_binding(G_COORD);
+  GeomBindType nb = geom->get_binding(G_NORMAL);
+  GeomBindType tb = geom->get_binding(G_TEXCOORD);
+  GeomBindType cb = geom->get_binding(G_COLOR);
+
+  Vertexf vertex;
+  Normalf normal;
+  TexCoordf uv;
+  Colorf color;
+
+  // Get overall properties.
+  if (vb == G_OVERALL) {
+    vertex = geom->get_next_vertex(vi);
+  }
+  if (nb == G_OVERALL) {
+    normal = geom->get_next_normal(ni);
+  }
+  if (tb == G_OVERALL) {
+    uv = geom->get_next_texcoord(ti);
+  }
+  if (cb == G_OVERALL) {
+    color = geom->get_next_color(ci);
+  }
+
+  for (int i = 0; i < nprims; i++) {
+    // Get per-prim properties.
+    if (vb == G_PER_PRIM) {
+      vertex = geom->get_next_vertex(vi);
+    }
+    if (nb == G_PER_PRIM) {
+      normal = geom->get_next_normal(ni);
+    }
+    if (tb == G_PER_PRIM) {
+      uv = geom->get_next_texcoord(ti);
+    }
+    if (cb == G_PER_PRIM) {
+      color = geom->get_next_color(ci);
+    }
+
+    EggPolygon *egg_poly = new EggPolygon;
+    egg_parent->add_child(egg_poly);
+    state.apply(egg_poly, _textures, _materials);
+
+    for (int j = 0; j < 3; j++) {
+      // Get per-vertex properties.
+      if (vb == G_PER_VERTEX) {
+        vertex = geom->get_next_vertex(vi);
+      }
+      if (nb == G_PER_VERTEX) {
+        normal = geom->get_next_normal(ni);
+      }
+      if (tb == G_PER_VERTEX) {
+        uv = geom->get_next_texcoord(ti);
+      }
+      if (cb == G_PER_VERTEX) {
+        color = geom->get_next_color(ci);
+      }
+
+      EggVertex egg_vert;
+      state.apply_vertex(egg_vert, vertex);
+      if (nb != G_OFF) {
+        state.apply_normal(egg_vert, normal);
+      }
+      if (tb != G_OFF) {
+        state.apply_uv(egg_vert, uv);
+      }
+      if (cb != G_OFF) {
+        state.apply_color(egg_vert, color);
+      }
+
+      EggVertex *new_egg_vert = _vpool->create_unique_vertex(egg_vert);
+      egg_poly->add_vertex(new_egg_vert);
+    }
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BamToEgg::recurse_nodes
+//       Access: Private
+//  Description: Converts all the children of the indicated node.
+////////////////////////////////////////////////////////////////////
+void BamToEgg::
+recurse_nodes(Node *node, ArcChain &chain, EggGroupNode *egg_parent) {
+  int num_children = node->get_num_children(RenderRelation::get_class_type());
+
+  for (int i = 0; i < num_children; i++) {
+    NodeRelation *arc = 
+      node->get_child(RenderRelation::get_class_type(), i);
+    ArcChain next_chain(chain);
+    next_chain.push_back(arc);
+    convert_node(arc->get_child(), next_chain, egg_parent);
+  }
+}
+
+
+int main(int argc, char *argv[]) {
+  BamToEgg prog;
+  prog.parse_command_line(argc, argv);
+  prog.run();
+  return 0;
+}

+ 84 - 0
pandatool/src/bam/bamToEgg.h

@@ -0,0 +1,84 @@
+// Filename: bamToEgg.h
+// Created by:  drose (25Jun01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef BAMTOEGG_H
+#define BAMTOEGG_H
+
+#include "pandatoolbase.h"
+
+#include "somethingToEgg.h"
+#include "luse.h"
+#include "eggTextureCollection.h"
+#include "eggMaterialCollection.h"
+
+class Node;
+class LODNode;
+class GeomNode;
+class ArcChain;
+class GeomTri;
+class EggVertexPool;
+class EggVertex;
+class EggPrimitive;
+class Texture;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BamToEgg
+// Description :
+////////////////////////////////////////////////////////////////////
+class BamToEgg : public SomethingToEgg {
+public:
+  BamToEgg();
+
+  void run();
+
+private:
+  class GeomState {
+  public:
+    GeomState();
+    void get_net_state(Node *node, ArcChain &chain);
+
+    void apply(EggPrimitive *egg_prim,
+               EggTextureCollection &textures,
+               EggMaterialCollection &materials);
+
+    void apply_vertex(EggVertex &egg_vert, const Vertexf &vertex);
+    void apply_normal(EggVertex &egg_vert, const Normalf &normal);
+    void apply_uv(EggVertex &egg_vert, const TexCoordf &uv);
+    void apply_color(EggVertex &egg_vert, const Colorf &color);
+
+    LMatrix4f _mat;
+    LMatrix4f _tex_mat;
+    LMatrix4f _color_mat;
+    float _alpha_scale;
+    float _alpha_offset;
+    Texture *_tex;
+  };
+
+  void convert_node(Node *node, ArcChain &chain, EggGroupNode *egg_parent);
+  void convert_lod_node(LODNode *node, ArcChain &chain, EggGroupNode *egg_parent);
+  void convert_geom_node(GeomNode *node, ArcChain &chain, EggGroupNode *egg_parent);
+  void convert_geom_tri(GeomTri *geom, GeomState &state, EggGroupNode *egg_parent);
+
+  void recurse_nodes(Node *node, ArcChain &chain, EggGroupNode *egg_parent);
+
+  EggVertexPool *_vpool;
+  EggTextureCollection _textures;
+  EggMaterialCollection _materials;
+};
+
+#endif