|
@@ -1,436 +0,0 @@
|
|
|
-// Filename: vrml2egg.C
|
|
|
|
|
-// Created by: drose (24Jun99)
|
|
|
|
|
-//
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
|
|
|
|
-//
|
|
|
|
|
-// These coded instructions, statements, data structures and
|
|
|
|
|
-// computer programs contain unpublished proprietary information of
|
|
|
|
|
-// Walt Disney Imagineering and are protected by Federal copyright
|
|
|
|
|
-// law. They may not be disclosed to third parties or copied or
|
|
|
|
|
-// duplicated in any form, in whole or in part, without the prior
|
|
|
|
|
-// written consent of Walt Disney Imagineering Inc.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-
|
|
|
|
|
-#include "vrml2egg.h"
|
|
|
|
|
-#include "parse_vrml.h"
|
|
|
|
|
-#include "vrmlNode.h"
|
|
|
|
|
-#include "appearance.h"
|
|
|
|
|
-#include "indexedFaceSet.h"
|
|
|
|
|
-#include "y.tab.h"
|
|
|
|
|
-
|
|
|
|
|
-#include <assert.h>
|
|
|
|
|
-#include <math.h>
|
|
|
|
|
-
|
|
|
|
|
-static const double pi = 4.0 * atan(1.0);
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::Help
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description: Displays the "what is this program" message, along
|
|
|
|
|
-// with the usage message. Should be overridden in base
|
|
|
|
|
-// classes to describe the current program.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-Help() {
|
|
|
|
|
- cerr <<
|
|
|
|
|
- "\n"
|
|
|
|
|
- "vrml2egg converts VRML 2.0 files (with the .wrl extension) to egg format.\n"
|
|
|
|
|
- "A reasonable subset of the VRML standard is supported, including polygons,\n"
|
|
|
|
|
- "colors, normals, textures, and hierarchy.\n";
|
|
|
|
|
-
|
|
|
|
|
- Usage();
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::Usage
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description: Displays the usage message.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-Usage() {
|
|
|
|
|
- cerr << "\nUsage:\n"
|
|
|
|
|
- << _commandName << " [opts] input.wrl\n\n"
|
|
|
|
|
-
|
|
|
|
|
- << "Options:\n";
|
|
|
|
|
-
|
|
|
|
|
- ShowOpts();
|
|
|
|
|
- cerr << "\n";
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::ShowOpts
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description: Displays the valid options. Should be extended in
|
|
|
|
|
-// base classes to show additional options relevant to
|
|
|
|
|
-// the current program.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-ShowOpts() {
|
|
|
|
|
- EggBase::ShowOpts();
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::HandleGetopts
|
|
|
|
|
-// Access: Public, Virtual
|
|
|
|
|
-// Description:
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-boolean MainProgram::
|
|
|
|
|
-HandleGetopts(char flag, char *optarg, int &optind,
|
|
|
|
|
- int argc, char **argv) {
|
|
|
|
|
- bool okflag = true;
|
|
|
|
|
-
|
|
|
|
|
- switch (flag) {
|
|
|
|
|
- default:
|
|
|
|
|
- okflag = EggBase::HandleGetopts(flag, optarg, optind, argc, argv);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return okflag;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::HandleArgs
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Called by EggBase::CommandLine() to do the right
|
|
|
|
|
-// thing with the arguments after the switches.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-boolean MainProgram::
|
|
|
|
|
-HandleArgs(int &argc, char **&argv) {
|
|
|
|
|
- if (argc != 2) {
|
|
|
|
|
- cerr << "VRML file name required.\n";
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- _filename = argv[1];
|
|
|
|
|
-
|
|
|
|
|
- return EggBase::HandleArgs(argc, argv);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::vrml_group
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Creates an Egg group corresponding to the VRML group.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-vrml_group(const VrmlNode *node, EggGroup *group,
|
|
|
|
|
- const pfMatrix &net_transform) {
|
|
|
|
|
- const MFArray *children = node->get_value("children")._mf;
|
|
|
|
|
- MFArray::const_iterator ci;
|
|
|
|
|
- for (ci = children->begin(); ci != children->end(); ++ci) {
|
|
|
|
|
- vrml_node((*ci)._sfnode, group, net_transform);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::vrml_transform
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Creates an Egg group with a transform corresponding
|
|
|
|
|
-// to the VRML group.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-vrml_transform(const VrmlNode *node, EggGroup *group,
|
|
|
|
|
- const pfMatrix &net_transform) {
|
|
|
|
|
- const double *scale = node->get_value("scale")._sfvec;
|
|
|
|
|
- const double *rotation = node->get_value("rotation")._sfvec;
|
|
|
|
|
- const double *translation = node->get_value("translation")._sfvec;
|
|
|
|
|
-
|
|
|
|
|
- const double *center = node->get_value("center")._sfvec;
|
|
|
|
|
- const double *o = node->get_value("scaleOrientation")._sfvec;
|
|
|
|
|
-
|
|
|
|
|
- pfMatrix local_transform;
|
|
|
|
|
- local_transform.makeIdent();
|
|
|
|
|
-
|
|
|
|
|
- boolean any_transform = false;
|
|
|
|
|
-
|
|
|
|
|
- if (scale[0] != 1.0 || scale[1] != 1.0 || scale[2] != 1.0) {
|
|
|
|
|
- any_transform = true;
|
|
|
|
|
- if (center[0] != 0.0 || center[1] != 0.0 || center[2] != 0.0) {
|
|
|
|
|
- local_transform.postTrans(local_transform,
|
|
|
|
|
- -center[0], -center[1], -center[2]);
|
|
|
|
|
- if (o[3] != 0.0) {
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- -o[3] * 180.0 / pi, o[0], o[1], o[2]);
|
|
|
|
|
- local_transform.postScale(local_transform,
|
|
|
|
|
- scale[0], scale[1], scale[2]);
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- o[3] * 180.0 / pi, o[0], o[1], o[2]);
|
|
|
|
|
- } else {
|
|
|
|
|
- local_transform.postScale(local_transform,
|
|
|
|
|
- scale[0], scale[1], scale[2]);
|
|
|
|
|
- }
|
|
|
|
|
- local_transform.postTrans(local_transform,
|
|
|
|
|
- center[0], center[1], center[2]);
|
|
|
|
|
- } else {
|
|
|
|
|
- if (o[3] != 0.0) {
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- -o[3] * 180.0 / pi, o[0], o[1], o[2]);
|
|
|
|
|
- local_transform.postScale(local_transform,
|
|
|
|
|
- scale[0], scale[1], scale[2]);
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- o[3] * 180.0 / pi, o[0], o[1], o[2]);
|
|
|
|
|
- } else {
|
|
|
|
|
- local_transform.postScale(local_transform,
|
|
|
|
|
- scale[0], scale[1], scale[2]);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (rotation[3] != 0.0) {
|
|
|
|
|
- any_transform = true;
|
|
|
|
|
- if (center[0] != 0.0 || center[1] != 0.0 || center[2] != 0.0) {
|
|
|
|
|
- local_transform.postTrans(local_transform,
|
|
|
|
|
- -center[0], -center[1], -center[2]);
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- rotation[3] * 180.0 / pi,
|
|
|
|
|
- rotation[0], rotation[1], rotation[2]);
|
|
|
|
|
- local_transform.postTrans(local_transform,
|
|
|
|
|
- center[0], center[1], center[2]);
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- local_transform.postRot(local_transform,
|
|
|
|
|
- rotation[3] * 180.0 / pi,
|
|
|
|
|
- rotation[0], rotation[1], rotation[2]);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (translation[0] != 0.0 ||
|
|
|
|
|
- translation[1] != 0.0 ||
|
|
|
|
|
- translation[2] != 0.0) {
|
|
|
|
|
- any_transform = true;
|
|
|
|
|
- local_transform.postTrans(local_transform,
|
|
|
|
|
- translation[0],
|
|
|
|
|
- translation[1],
|
|
|
|
|
- translation[2]);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (any_transform) {
|
|
|
|
|
- group->transform = local_transform;
|
|
|
|
|
- group->flags |= EF_TRANSFORM;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- pfMatrix next_transform = local_transform * net_transform;
|
|
|
|
|
-
|
|
|
|
|
- const MFArray *children = node->get_value("children")._mf;
|
|
|
|
|
- MFArray::const_iterator ci;
|
|
|
|
|
- for (ci = children->begin(); ci != children->end(); ++ci) {
|
|
|
|
|
- vrml_node((*ci)._sfnode, group, next_transform);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::vrml_shape
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Creates an Egg group corresponding a VRML shape.
|
|
|
|
|
-// This will probably contain a vertex pool and a number
|
|
|
|
|
-// of polygons.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-vrml_shape(const VrmlNode *node, EggGroup *group,
|
|
|
|
|
- const pfMatrix &net_transform) {
|
|
|
|
|
- const VrmlNode *geometry = node->get_value("geometry")._sfnode._p;
|
|
|
|
|
-
|
|
|
|
|
- double transparency = 0.0;
|
|
|
|
|
-
|
|
|
|
|
- if (geometry != NULL) {
|
|
|
|
|
- Appearance appearance
|
|
|
|
|
- (node->get_value("appearance")._sfnode._p, _data);
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(geometry->_type->getName(), "IndexedFaceSet") == 0) {
|
|
|
|
|
- IndexedFaceSet ifs(geometry, appearance, _data);
|
|
|
|
|
- ifs.convert_to_egg(group, net_transform);
|
|
|
|
|
- } else {
|
|
|
|
|
- cerr << "Ignoring " << geometry->_type->getName() << "\n";
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::vrml_grouping_node
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Begins initial processing of a grouping-type node;
|
|
|
|
|
-// that is, any node (like Group, Transform, or Shape)
|
|
|
|
|
-// that maps to a <Group> or <Instance> in egg. This
|
|
|
|
|
-// create the group and does any instance-munging
|
|
|
|
|
-// necessary, then calls the indicated method with the
|
|
|
|
|
-// new parameters.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-vrml_grouping_node(const SFNodeRef &vrml, EggGroup *egg,
|
|
|
|
|
- const pfMatrix &net_transform,
|
|
|
|
|
- void (MainProgram::*process_func)
|
|
|
|
|
- (const VrmlNode *node, EggGroup *group,
|
|
|
|
|
- const pfMatrix &net_transform)) {
|
|
|
|
|
- const VrmlNode *node = vrml._p;
|
|
|
|
|
- assert(node != NULL);
|
|
|
|
|
- const char *name = vrml._name;
|
|
|
|
|
-
|
|
|
|
|
- if (vrml._type == SFNodeRef::T_use) {
|
|
|
|
|
- // If this is an instancing reference, just add the reference and
|
|
|
|
|
- // return; no need for further processing on the node.
|
|
|
|
|
- Instances::const_iterator fi = _instances.find(node);
|
|
|
|
|
- assert(fi != _instances.end());
|
|
|
|
|
- EggInstance *inst = _data.CreateInstance(egg);
|
|
|
|
|
- inst->AddGroupRef((*fi).second);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- EggGroup *group;
|
|
|
|
|
- pfMatrix next_transform;
|
|
|
|
|
-
|
|
|
|
|
- if (node->_use_count > 0) {
|
|
|
|
|
- // If this node is referenced one or more times later in the file,
|
|
|
|
|
- // we must make it an instance node.
|
|
|
|
|
- group = _data.CreateInstance(egg, name);
|
|
|
|
|
- next_transform.makeIdent();
|
|
|
|
|
-
|
|
|
|
|
- // And define the instance for future references.
|
|
|
|
|
- _instances[node] = group;
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- group = _data.CreateGroup(egg, name);
|
|
|
|
|
- next_transform = net_transform;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- (this->*process_func)(node, group, next_transform);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::vrml_node
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Processes a single VRML node, converting it to egg
|
|
|
|
|
-// and adding it to the egg file, if appropriate, or
|
|
|
|
|
-// doing whatever else should be done.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-vrml_node(const SFNodeRef &vrml, EggGroup *egg,
|
|
|
|
|
- const pfMatrix &net_transform) {
|
|
|
|
|
- const VrmlNode *node = vrml._p;
|
|
|
|
|
- if (node != NULL) {
|
|
|
|
|
- // Now add it to the egg file at this point.
|
|
|
|
|
- if (strcmp(node->_type->getName(), "Group") == 0) {
|
|
|
|
|
- vrml_grouping_node(vrml, egg, net_transform, &vrml_group);
|
|
|
|
|
- } else if (strcmp(node->_type->getName(), "Transform") == 0) {
|
|
|
|
|
- vrml_grouping_node(vrml, egg, net_transform, &vrml_transform);
|
|
|
|
|
- } else if (strcmp(node->_type->getName(), "Shape") == 0) {
|
|
|
|
|
- vrml_grouping_node(vrml, egg, net_transform, &vrml_shape);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::get_all_defs
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description: Makes a first pass through the VRML hierarchy,
|
|
|
|
|
-// identifying all nodes marked with a DEF code, and
|
|
|
|
|
-// also counting the times each one is referenced by
|
|
|
|
|
-// USE. Later, we'll need this information: if a node
|
|
|
|
|
-// is referenced at least once, we need to define it as
|
|
|
|
|
-// an instance node.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-get_all_defs(SFNodeRef &vrml, MainProgram::Nodes &nodes) {
|
|
|
|
|
- Nodes::iterator ni;
|
|
|
|
|
-
|
|
|
|
|
- switch (vrml._type) {
|
|
|
|
|
- case SFNodeRef::T_def:
|
|
|
|
|
- // If this is a node definition, add it to the map.
|
|
|
|
|
- assert(vrml._name != NULL);
|
|
|
|
|
- assert(vrml._p != NULL);
|
|
|
|
|
- /*
|
|
|
|
|
- This happens too often to bother yelling about it.
|
|
|
|
|
- ni = nodes.find(vrml._name);
|
|
|
|
|
- if (ni != nodes.end()) {
|
|
|
|
|
- cerr << "Warning: node name " << vrml._name
|
|
|
|
|
- << " appears multiple times.\n";
|
|
|
|
|
- }
|
|
|
|
|
- */
|
|
|
|
|
- nodes[vrml._name] = vrml._p;
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case SFNodeRef::T_use:
|
|
|
|
|
- // If it's a reference, resolve it.
|
|
|
|
|
- assert(vrml._name != NULL);
|
|
|
|
|
- ni = nodes.find(vrml._name);
|
|
|
|
|
- if (ni == nodes.end()) {
|
|
|
|
|
- cerr << "Unknown node reference: " << vrml._name << "\n";
|
|
|
|
|
- } else {
|
|
|
|
|
- // Increment the use count of the node.
|
|
|
|
|
- (*ni).second->_use_count++;
|
|
|
|
|
-
|
|
|
|
|
- // Store the pointer itself in the reference, so we don't have
|
|
|
|
|
- // to do this again later.
|
|
|
|
|
- vrml._p = (*ni).second;
|
|
|
|
|
- }
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- VrmlNode *node = vrml._p;
|
|
|
|
|
- if (node != NULL) {
|
|
|
|
|
- VrmlNode::Fields::iterator fi;
|
|
|
|
|
- for (fi = node->_fields.begin(); fi != node->_fields.end(); ++fi) {
|
|
|
|
|
- if ((*fi)._type->type == SFNODE) {
|
|
|
|
|
- get_all_defs((*fi)._value._sfnode, nodes);
|
|
|
|
|
- } else if ((*fi)._type->type == MFNODE) {
|
|
|
|
|
- MFArray *children = (*fi)._value._mf;
|
|
|
|
|
- MFArray::iterator ci;
|
|
|
|
|
- for (ci = children->begin(); ci != children->end(); ++ci) {
|
|
|
|
|
- get_all_defs((*ci)._sfnode, nodes);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: MainProgram::DoIt
|
|
|
|
|
-// Access: Public
|
|
|
|
|
-// Description:
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-void MainProgram::
|
|
|
|
|
-DoIt() {
|
|
|
|
|
- VrmlScene *scene = parse_vrml(_filename.c_str());
|
|
|
|
|
- if (scene != NULL) {
|
|
|
|
|
- // First, resolve all the DEF/USE references, and count the number
|
|
|
|
|
- // of times each node is USEd.
|
|
|
|
|
- Nodes nodes;
|
|
|
|
|
- VrmlScene::iterator si;
|
|
|
|
|
- for (si = scene->begin(); si != scene->end(); ++si) {
|
|
|
|
|
- get_all_defs((*si)._node, nodes);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Now go through the hierarchy again, and this time actually
|
|
|
|
|
- // build the egg structure.
|
|
|
|
|
- pfMatrix ident;
|
|
|
|
|
- ident.makeIdent();
|
|
|
|
|
-
|
|
|
|
|
- VrmlScene::const_iterator csi;
|
|
|
|
|
- for (csi = scene->begin(); csi != scene->end(); ++csi) {
|
|
|
|
|
- vrml_node((*csi)._node, &_data.root_group, ident);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- _data.UniquifyNames();
|
|
|
|
|
- Output() << _data << "\n";
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-int
|
|
|
|
|
-main(int argc, char *argv[]) {
|
|
|
|
|
- pfInitArenas();
|
|
|
|
|
-
|
|
|
|
|
- MainProgram prog;
|
|
|
|
|
-
|
|
|
|
|
- if (prog.CommandLine(argc, argv)) {
|
|
|
|
|
- prog.DoIt();
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- return 1;
|
|
|
|
|
-}
|
|
|