add egg2bam

This commit is contained in:
David Rose 2001-06-26 17:28:51 +00:00
parent 4d4833e601
commit 5e4ce3a6df
3 changed files with 600 additions and 0 deletions

View File

@ -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

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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;
}

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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