port vrml2egg from DWDTOOL

This commit is contained in:
David Rose 2004-10-01 23:20:09 +00:00
parent c8e39f5cff
commit c5dc6f45c7
33 changed files with 6240 additions and 1 deletions

View File

@ -93,6 +93,10 @@ bool DXFToEggConverter::
convert_file(const Filename &filename) {
_error = false;
if (_egg_data->get_coordinate_system() == CS_default) {
_egg_data->set_coordinate_system(CS_zup_right);
}
process(filename);
return !_error;
}

View File

@ -2,7 +2,7 @@
#define TARGET ptloader
#define BUILDING_DLL BUILDING_PTLOADER
#define LOCAL_LIBS \
fltegg flt lwoegg lwo dxfegg dxf converter pandatoolbase
fltegg flt lwoegg lwo dxfegg dxf vrmlegg pvrml converter pandatoolbase
#define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \
mathutil:c linmath:c putil:c \

View File

@ -24,6 +24,7 @@
#include "config_lwo.h"
#include "lwoToEggConverter.h"
#include "dxfToEggConverter.h"
#include "vrmlToEggConverter.h"
/*
#ifdef HAVE_DX
@ -85,6 +86,9 @@ init_libptloader() {
DXFToEggConverter *dxf = new DXFToEggConverter;
reg->register_type(new LoaderFileTypePandatool(dxf));
VRMLToEggConverter *vrml = new VRMLToEggConverter;
reg->register_type(new LoaderFileTypePandatool(vrml));
/*
#ifdef HAVE_DX
init_libxfile();

View File

@ -0,0 +1,21 @@
#define YACC_PREFIX vrmlyy
#begin ss_lib_target
#define TARGET pvrml
#define LOCAL_LIBS \
pandatoolbase
#define OTHER_LIBS \
mathutil:c linmath:c panda:m \
dtoolbase:c dtool:m
#define USE_PACKAGES zlib
#define SOURCES \
parse_vrml.cxx parse_vrml.h \
standard_nodes.cxx standard_nodes.h \
vrmlLexer.lxx \
vrmlParser.yxx \
vrmlNode.cxx vrmlNode.h \
vrmlNodeType.cxx vrmlNodeType.h
#end ss_lib_target

View File

@ -0,0 +1,142 @@
// Filename: parse_vrml.cxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
/**************************************************
* VRML 2.0, Draft 2 Parser
* Copyright (C) 1996 Silicon Graphics, Inc.
*
* Author(s) : Gavin Bell
* Daniel Woods (first port)
**************************************************
*/
#include "pandatoolbase.h"
#include "parse_vrml.h"
#include "vrmlParserDefs.h"
#include "vrmlNodeType.h"
#include "vrmlNode.h"
#include "standard_nodes.h"
#include "zStream.h"
extern int vrmlyyparse();
extern void vrmlyyResetLineNumber();
extern int vrmlyydebug;
extern int vrmlyy_flex_debug;
extern FILE *vrmlyyin;
extern VrmlScene *parsed_scene;
////////////////////////////////////////////////////////////////////
// Function: get_standard_nodes
// Description: Loads the set of standard VRML node definitions into
// the parser, if it has not already been loaded.
////////////////////////////////////////////////////////////////////
static bool
get_standard_nodes() {
static bool got_standard_nodes = false;
static bool read_ok = true;
if (got_standard_nodes) {
return read_ok;
}
// The standardNodes.wrl file has been compiled into this binary.
// Extract it out.
string data((const char *)standard_nodes_data, standard_nodes_data_len);
#ifdef HAVE_ZLIB
// The data is stored compressed; decompress it on-the-fly.
istringstream inz(data);
IDecompressStream in(&inz, false);
#else
// The data is stored uncompressed, so just load it.
istringstream in(data);
#endif // HAVE_ZLIB
vrml_init_parser(in, "standardNodes.wrl");
if (vrmlyyparse() != 0) {
read_ok = false;
}
vrml_cleanup_parser();
got_standard_nodes = true;
return read_ok;
}
////////////////////////////////////////////////////////////////////
// Function: parse_vrml
// Description: Reads the named VRML file and returns a corresponding
// VrmlScene, or NULL if there is a parse error.
////////////////////////////////////////////////////////////////////
VrmlScene *
parse_vrml(Filename filename) {
filename.set_text();
ifstream infile;
if (!filename.open_read(infile)) {
cerr << "Error, couldn't open " << filename << "\n";
return NULL;
}
return parse_vrml(infile, filename);
}
////////////////////////////////////////////////////////////////////
// Function: parse_vrml
// Description: Reads the indicated input stream and returns a corresponding
// VrmlScene, or NULL if there is a parse error.
////////////////////////////////////////////////////////////////////
VrmlScene *
parse_vrml(istream &in, const string &filename) {
if (!get_standard_nodes()) {
cerr << "Internal error--unable to parse VRML.\n";
return NULL;
}
VrmlScene *scene = NULL;
VrmlNodeType::pushNameSpace();
vrml_init_parser(in, filename);
if (vrmlyyparse() == 0) {
scene = parsed_scene;
}
vrml_cleanup_parser();
VrmlNodeType::popNameSpace();
return scene;
}
#if 0
int
main(int argc, char *argv[]) {
if (argc < 2) {
cerr << "parse_vrml filename.wrl\n";
exit(1);
}
VrmlScene *scene = parse_vrml(argv[1]);
if (scene == (VrmlScene *)NULL) {
exit(1);
}
cout << *scene << "\n";
return (0);
}
#endif

View File

@ -0,0 +1,24 @@
// Filename: parse_vrml.h
// 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.
////////////////////////////////////////////////////////////////////
#ifndef PARSE_VRML_H
#define PARSE_VRML_H
#include "vrmlNode.h"
#include "filename.h"
VrmlScene *parse_vrml(Filename filename);
VrmlScene *parse_vrml(istream &in, const string &filename);
#endif

View File

@ -0,0 +1,488 @@
#VRML V2.0 utf8
#
# **************************************************
# * VRML 2.0 Parser
# * Copyright (C) 1996 Silicon Graphics, Inc.
# *
# * Author(s) : Gavin Bell
# * Daniel Woods (first port)
# **************************************************
#
# Definitions for all of the nodes built-in to the spec.
# Taken almost directly from the VRML 2.0 final spec:
PROTO Anchor [
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField MFNode children []
exposedField SFString description ""
exposedField MFString parameter []
exposedField MFString url []
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
] { }
PROTO Appearance [
exposedField SFNode material NULL
exposedField SFNode texture NULL
exposedField SFNode textureTransform NULL
] { }
PROTO AudioClip [
exposedField SFString description ""
exposedField SFBool loop FALSE
exposedField SFFloat pitch 1.0
exposedField SFTime startTime 0
exposedField SFTime stopTime 0
exposedField MFString url []
eventOut SFTime duration_changed
eventOut SFBool isActive
] { }
PROTO Background [
eventIn SFBool set_bind
exposedField MFFloat groundAngle []
exposedField MFColor groundColor []
exposedField MFString backUrl []
exposedField MFString bottomUrl []
exposedField MFString frontUrl []
exposedField MFString leftUrl []
exposedField MFString rightUrl []
exposedField MFString topUrl []
exposedField MFFloat skyAngle []
exposedField MFColor skyColor [ 0 0 0 ]
eventOut SFBool isBound
] { }
PROTO Billboard [
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField SFVec3f axisOfRotation 0 1 0
exposedField MFNode children []
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
] { }
PROTO Box [
field SFVec3f size 2 2 2
] { }
PROTO Collision [
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField MFNode children []
exposedField SFBool collide TRUE
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
field SFNode proxy NULL
eventOut SFTime collideTime
] { }
PROTO Color [
exposedField MFColor color []
] { }
PROTO ColorInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFColor keyValue []
eventOut SFColor value_changed
] { }
PROTO Cone [
field SFFloat bottomRadius 1
field SFFloat height 2
field SFBool side TRUE
field SFBool bottom TRUE
] { }
PROTO Coordinate [
exposedField MFVec3f point []
] { }
PROTO CoordinateInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFVec3f keyValue []
eventOut MFVec3f value_changed
] { }
PROTO Cylinder [
field SFBool bottom TRUE
field SFFloat height 2
field SFFloat radius 1
field SFBool side TRUE
field SFBool top TRUE
] { }
PROTO CylinderSensor [
exposedField SFBool autoOffset TRUE
exposedField SFFloat diskAngle 0.262
exposedField SFBool enabled TRUE
exposedField SFFloat maxAngle -1
exposedField SFFloat minAngle 0
exposedField SFFloat offset 0
eventOut SFBool isActive
eventOut SFRotation rotation_changed
eventOut SFVec3f trackPoint_changed
] { }
PROTO DirectionalLight [
exposedField SFFloat ambientIntensity 0
exposedField SFColor color 1 1 1
exposedField SFVec3f direction 0 0 -1
exposedField SFFloat intensity 1
exposedField SFBool on TRUE
] { }
PROTO ElevationGrid [
eventIn MFFloat set_height
exposedField SFNode color NULL
exposedField SFNode normal NULL
exposedField SFNode texCoord NULL
field SFBool ccw TRUE
field SFBool colorPerVertex TRUE
field SFFloat creaseAngle 0
field MFFloat height []
field SFBool normalPerVertex TRUE
field SFBool solid TRUE
field SFInt32 xDimension 0
field SFFloat xSpacing 0.0
field SFInt32 zDimension 0
field SFFloat zSpacing 0.0
] { }
PROTO Extrusion [
eventIn MFVec2f set_crossSection
eventIn MFRotation set_orientation
eventIn MFVec2f set_scale
eventIn MFVec3f set_spine
field SFBool beginCap TRUE
field SFBool ccw TRUE
field SFBool convex TRUE
field SFFloat creaseAngle 0
field MFVec2f crossSection [ 1 1, 1 -1, -1 -1, -1 1, 1 1 ]
field SFBool endCap TRUE
field MFRotation orientation 0 0 1 0
field MFVec2f scale 1 1
field SFBool solid TRUE
field MFVec3f spine [ 0 0 0, 0 1 0 ]
] { }
PROTO Fog [
exposedField SFColor color 1 1 1
exposedField SFString fogType "LINEAR"
exposedField SFFloat visibilityRange 0
eventIn SFBool set_bind
eventOut SFBool isBound
] { }
PROTO FontStyle [
field SFString family "SERIF"
field SFBool horizontal TRUE
field MFString justify "BEGIN"
field SFString language ""
field SFBool leftToRight TRUE
field SFFloat size 1.0
field SFFloat spacing 1.0
field SFString style "PLAIN"
field SFBool topToBottom TRUE
] { }
PROTO Group [
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField MFNode children []
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
] { }
PROTO ImageTexture [
exposedField MFString url []
field SFBool repeatS TRUE
field SFBool repeatT TRUE
] { }
PROTO IndexedFaceSet [
eventIn MFInt32 set_colorIndex
eventIn MFInt32 set_coordIndex
eventIn MFInt32 set_normalIndex
eventIn MFInt32 set_texCoordIndex
exposedField SFNode color NULL
exposedField SFNode coord NULL
exposedField SFNode normal NULL
exposedField SFNode texCoord NULL
field SFBool ccw TRUE
field MFInt32 colorIndex []
field SFBool colorPerVertex TRUE
field SFBool convex TRUE
field MFInt32 coordIndex []
field SFFloat creaseAngle 0
field MFInt32 normalIndex []
field SFBool normalPerVertex TRUE
field SFBool solid TRUE
field MFInt32 texCoordIndex []
] { }
PROTO IndexedLineSet [
eventIn MFInt32 set_colorIndex
eventIn MFInt32 set_coordIndex
exposedField SFNode color NULL
exposedField SFNode coord NULL
field MFInt32 colorIndex []
field SFBool colorPerVertex TRUE
field MFInt32 coordIndex []
] { }
PROTO Inline [
exposedField MFString url []
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
] { }
PROTO LOD [
exposedField MFNode level []
field SFVec3f center 0 0 0
field MFFloat range []
] { }
PROTO Material [
exposedField SFFloat ambientIntensity 0.2
exposedField SFColor diffuseColor 0.8 0.8 0.8
exposedField SFColor emissiveColor 0 0 0
exposedField SFFloat shininess 0.2
exposedField SFColor specularColor 0 0 0
exposedField SFFloat transparency 0
] { }
PROTO MovieTexture [
exposedField SFBool loop FALSE
exposedField SFFloat speed 1
exposedField SFTime startTime 0
exposedField SFTime stopTime 0
exposedField MFString url []
field SFBool repeatS TRUE
field SFBool repeatT TRUE
eventOut SFFloat duration_changed
eventOut SFBool isActive
] { }
PROTO NavigationInfo [
eventIn SFBool set_bind
exposedField MFFloat avatarSize [ 0.25, 1.6, 0.75 ]
exposedField SFBool headlight TRUE
exposedField SFFloat speed 1.0
exposedField MFString type "WALK"
exposedField SFFloat visibilityLimit 0.0
eventOut SFBool isBound
] { }
PROTO Normal [
exposedField MFVec3f vector []
] { }
PROTO NormalInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFVec3f keyValue []
eventOut MFVec3f value_changed
] { }
PROTO OrientationInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFRotation keyValue []
eventOut SFRotation value_changed
] { }
PROTO PixelTexture [
exposedField SFImage image 0 0 0
field SFBool repeatS TRUE
field SFBool repeatT TRUE
] { }
PROTO PlaneSensor [
exposedField SFBool autoOffset TRUE
exposedField SFBool enabled TRUE
exposedField SFVec2f maxPosition -1 -1
exposedField SFVec2f minPosition 0 0
exposedField SFVec3f offset 0 0 0
eventOut SFBool isActive
eventOut SFVec3f trackPoint_changed
eventOut SFVec3f translation_changed
] { }
PROTO PointLight [
exposedField SFFloat ambientIntensity 0
exposedField SFVec3f attenuation 1 0 0
exposedField SFColor color 1 1 1
exposedField SFFloat intensity 1
exposedField SFVec3f location 0 0 0
exposedField SFBool on TRUE
exposedField SFFloat radius 100
] { }
PROTO PointSet [
exposedField SFNode color NULL
exposedField SFNode coord NULL
] { }
PROTO PositionInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFVec3f keyValue []
eventOut SFVec3f value_changed
] { }
PROTO ProximitySensor [
exposedField SFVec3f center 0 0 0
exposedField SFVec3f size 0 0 0
exposedField SFBool enabled TRUE
eventOut SFBool isActive
eventOut SFVec3f position_changed
eventOut SFRotation orientation_changed
eventOut SFTime enterTime
eventOut SFTime exitTime
] { }
PROTO ScalarInterpolator [
eventIn SFFloat set_fraction
exposedField MFFloat key []
exposedField MFFloat keyValue []
eventOut SFFloat value_changed
] { }
PROTO Script [
exposedField MFString url [ ]
field SFBool directOutput FALSE
field SFBool mustEvaluate FALSE
] { }
PROTO Shape [
field SFNode appearance NULL
field SFNode geometry NULL
] { }
PROTO Sound [
exposedField SFVec3f direction 0 0 1
exposedField SFFloat intensity 1
exposedField SFVec3f location 0 0 0
exposedField SFFloat maxBack 10
exposedField SFFloat maxFront 10
exposedField SFFloat minBack 1
exposedField SFFloat minFront 1
exposedField SFFloat priority 0
exposedField SFNode source NULL
field SFBool spatialize TRUE
] { }
PROTO Sphere [
field SFFloat radius 1
] { }
PROTO SphereSensor [
exposedField SFBool autoOffset TRUE
exposedField SFBool enabled TRUE
exposedField SFRotation offset 0 1 0 0
eventOut SFBool isActive
eventOut SFRotation rotation_changed
eventOut SFVec3f trackPoint_changed
] { }
PROTO SpotLight [
exposedField SFFloat ambientIntensity 0
exposedField SFVec3f attenuation 1 0 0
exposedField SFFloat beamWidth 1.570796
exposedField SFColor color 1 1 1
exposedField SFFloat cutOffAngle 0.785398
exposedField SFVec3f direction 0 0 -1
exposedField SFFloat intensity 1
exposedField SFVec3f location 0 0 0
exposedField SFBool on TRUE
exposedField SFFloat radius 100
] { }
PROTO Switch [
exposedField MFNode choice []
exposedField SFInt32 whichChild -1
] { }
PROTO Text [
exposedField MFString string []
field SFNode fontStyle NULL
field MFFloat length []
field SFFloat maxExtent 0.0
] { }
PROTO TextureCoordinate [
exposedField MFVec2f point []
] { }
PROTO TextureTransform [
exposedField SFVec2f center 0 0
exposedField SFFloat rotation 0
exposedField SFVec2f scale 1 1
exposedField SFVec2f translation 0 0
] { }
PROTO TimeSensor [
exposedField SFTime cycleInterval 1
exposedField SFBool enabled TRUE
exposedField SFBool loop FALSE
exposedField SFTime startTime 0
exposedField SFTime stopTime 0
eventOut SFTime cycleTime
eventOut SFFloat fraction_changed
eventOut SFBool isActive
eventOut SFTime time
] { }
PROTO TouchSensor [
exposedField SFBool enabled TRUE
eventOut SFVec3f hitNormal_changed
eventOut SFVec3f hitPoint_changed
eventOut SFVec2f hitTexCoord_changed
eventOut SFBool isActive
eventOut SFBool isOver
eventOut SFTime touchTime
] { }
PROTO Transform [
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField SFVec3f center 0 0 0
exposedField MFNode children []
exposedField SFRotation rotation 0 0 1 0
exposedField SFVec3f scale 1 1 1
exposedField SFRotation scaleOrientation 0 0 1 0
exposedField SFVec3f translation 0 0 0
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
] { }
PROTO Viewpoint [
eventIn SFBool set_bind
exposedField SFFloat fieldOfView 0.785398
exposedField SFBool jump TRUE
exposedField SFRotation orientation 0 0 1 0
exposedField SFVec3f position 0 0 10
field SFString description ""
eventOut SFTime bindTime
eventOut SFBool isBound
] { }
PROTO VisibilitySensor [
exposedField SFVec3f center 0 0 0
exposedField SFBool enabled TRUE
exposedField SFVec3f size 0 0 0
eventOut SFTime enterTime
eventOut SFTime exitTime
eventOut SFBool isActive
] { }
PROTO WorldInfo [
field MFString info []
field SFString title ""
] { }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
/*
* This table was generated by the command:
*
* bin2c -n standard_nodes_data -o standardNodes.wrl.pz.c standardNodes.wrl.pz
*/
const unsigned char standard_nodes_data[] = {
0x78, 0x9c, 0xd5, 0x5b, 0x5b, 0x6f, 0xdb, 0x38, 0x16, 0x7e, 0xcf,
0xaf, 0x20, 0xd2, 0x97, 0x76, 0xd1, 0x09, 0x62, 0x17, 0xbd, 0xcd,
0x5b, 0x92, 0x26, 0x45, 0xb0, 0x69, 0x12, 0x44, 0x6e, 0xfa, 0x50,
0x14, 0x03, 0x5a, 0xa2, 0x6d, 0x4e, 0x64, 0x51, 0xa0, 0x28, 0xd7,
0xee, 0x62, 0xff, 0xfb, 0xf2, 0x2e, 0x4a, 0xbc, 0x58, 0xdd, 0x66,
0x3a, 0x1d, 0xa5, 0x45, 0xd3, 0xf8, 0xd3, 0xe1, 0xe1, 0x39, 0x87,
0xe7, 0xca, 0x3c, 0xb9, 0xbf, 0xfb, 0x70, 0x05, 0xee, 0xa7, 0x47,
0xc7, 0xa0, 0x65, 0x8b, 0x37, 0x07, 0x4f, 0x0e, 0x9e, 0x80, 0x7f,
0x7d, 0xf7, 0x23, 0x5e, 0x02, 0x92, 0x92, 0x20, 0x74, 0x0b, 0x69,
0x83, 0xa8, 0xfc, 0xd9, 0x19, 0xa9, 0x77, 0x14, 0x2f, 0x57, 0x0c,
0x3c, 0x3d, 0x7b, 0x06, 0x26, 0x6f, 0xdf, 0xbe, 0x02, 0x19, 0x2e,
0x71, 0x4e, 0x2a, 0xf0, 0x9e, 0xc2, 0x7a, 0x85, 0xf3, 0xe6, 0x39,
0xb8, 0xac, 0xf2, 0x23, 0x81, 0x96, 0x6f, 0x9c, 0xb4, 0x6c, 0x45,
0xe8, 0xd3, 0xe6, 0x19, 0xe0, 0xcf, 0xef, 0xe0, 0x3d, 0xdc, 0xe0,
0x0a, 0x9c, 0xa2, 0xb2, 0x94, 0x9f, 0x0e, 0x9e, 0x77, 0xb0, 0xc2,
0xa8, 0x04, 0x9f, 0x08, 0x29, 0x1a, 0xf0, 0x74, 0x81, 0x69, 0xc3,
0x40, 0x4d, 0x28, 0x7b, 0xf6, 0x7f, 0xee, 0x82, 0xbf, 0xf6, 0x0e,
0x2d, 0x70, 0x85, 0x19, 0x26, 0x55, 0x03, 0x16, 0x84, 0x02, 0x58,
0x96, 0x80, 0x2c, 0x00, 0x5b, 0x21, 0x50, 0x91, 0x02, 0x35, 0x60,
0xde, 0xe2, 0x92, 0xfd, 0xc6, 0x99, 0x62, 0x44, 0xfe, 0xb4, 0xa9,
0x91, 0x64, 0x7f, 0x06, 0x1f, 0x50, 0xc5, 0xe1, 0x6b, 0xc2, 0x99,
0x28, 0x30, 0x45, 0x39, 0x2b, 0x77, 0x60, 0x41, 0xc9, 0x5a, 0xc2,
0xac, 0x74, 0x38, 0x79, 0x58, 0xca, 0xb7, 0x7e, 0x3f, 0x38, 0xb8,
0xbd, 0xbb, 0x99, 0xdd, 0x80, 0x93, 0x2a, 0xe7, 0x7b, 0x06, 0x9f,
0x0f, 0x00, 0x40, 0x1b, 0x54, 0xb1, 0xcb, 0x4a, 0x6d, 0xef, 0xc3,
0xc5, 0x35, 0x5f, 0x92, 0x7f, 0x03, 0x8b, 0xe2, 0x6c, 0x85, 0xcb,
0x82, 0xa2, 0x2a, 0x8a, 0xa1, 0x68, 0x4d, 0x36, 0xc8, 0x85, 0x6d,
0x6b, 0xd2, 0xa0, 0xe2, 0x82, 0x4b, 0xa8, 0xe8, 0x60, 0xb9, 0x06,
0x18, 0x11, 0x7e, 0xfe, 0x32, 0x84, 0x66, 0x17, 0x19, 0xa3, 0xb8,
0x5a, 0x02, 0xbe, 0xdb, 0x9c, 0xe2, 0x5a, 0xc8, 0x42, 0x42, 0x0f,
0x0f, 0x81, 0x4f, 0x56, 0x63, 0x6b, 0x48, 0xe1, 0x1a, 0x31, 0x44,
0xa3, 0x64, 0x2d, 0xb4, 0xa5, 0x65, 0x4f, 0x89, 0x12, 0xba, 0x90,
0x18, 0xfd, 0x64, 0x17, 0xf7, 0x28, 0x7f, 0xb1, 0x00, 0x60, 0x3e,
0x27, 0xdb, 0x33, 0xbe, 0x59, 0x43, 0xf6, 0x58, 0x7c, 0x25, 0xd1,
0x19, 0xfe, 0x86, 0xcc, 0x07, 0xbf, 0x4d, 0xd4, 0x9f, 0x83, 0x2f,
0xe0, 0x3f, 0xe0, 0xbf, 0x56, 0xd8, 0x75, 0x8d, 0x38, 0xb3, 0x55,
0x8e, 0x94, 0xc0, 0xfb, 0x5b, 0x97, 0x52, 0x5a, 0x43, 0xbe, 0x22,
0x86, 0x0e, 0x9b, 0xd7, 0x1f, 0xaf, 0xae, 0x22, 0x60, 0x86, 0xb6,
0xac, 0xa5, 0x08, 0x7c, 0x0f, 0x78, 0xc6, 0xd7, 0x6f, 0xb8, 0x75,
0xad, 0x35, 0xb8, 0xcf, 0x60, 0x5b, 0x60, 0x72, 0x56, 0xe2, 0xda,
0xe7, 0x0f, 0x44, 0x94, 0x73, 0x78, 0x18, 0x42, 0x9e, 0x12, 0x22,
0xb6, 0x50, 0x12, 0x52, 0x5b, 0xde, 0x2e, 0x4e, 0xae, 0xb2, 0xf3,
0x10, 0xf8, 0xa2, 0x24, 0x90, 0x01, 0x50, 0x63, 0x96, 0xaf, 0x0c,
0x78, 0x72, 0x74, 0x1c, 0x82, 0xce, 0xf0, 0x5a, 0x6c, 0xb7, 0x61,
0x90, 0x32, 0xfd, 0x3d, 0x48, 0x03, 0x49, 0x6d, 0x70, 0x21, 0x60,
0xd8, 0x32, 0x94, 0x05, 0x09, 0x53, 0xbf, 0x69, 0x99, 0x55, 0xb5,
0xa6, 0x53, 0xb4, 0x14, 0x8a, 0xad, 0xff, 0x91, 0xaf, 0x60, 0xb5,
0x44, 0x45, 0x08, 0xaa, 0xb7, 0x8f, 0x9b, 0x93, 0x9c, 0xe1, 0x0d,
0xea, 0x0b, 0xf9, 0x14, 0xe6, 0x0f, 0x4b, 0x4a, 0xda, 0xaa, 0xf0,
0x8f, 0x9d, 0x7d, 0xb5, 0x41, 0xec, 0x8f, 0x39, 0xae, 0x0a, 0xdf,
0x94, 0xb5, 0xb4, 0x14, 0x85, 0x93, 0x6a, 0x59, 0xa2, 0xb0, 0xc9,
0x9f, 0x91, 0x92, 0x1f, 0x6c, 0x8d, 0xd3, 0xff, 0x49, 0x1c, 0x8d,
0x39, 0xe7, 0xea, 0xa3, 0x11, 0x42, 0x0a, 0x47, 0x18, 0x23, 0x6b,
0x8d, 0x4c, 0xe0, 0xb8, 0xf7, 0xa9, 0x98, 0x21, 0x98, 0xc0, 0x95,
0x68, 0xc1, 0xc6, 0xac, 0x2b, 0x5d, 0xf9, 0x08, 0x7a, 0x5c, 0xe1,
0x96, 0x5c, 0x10, 0xa7, 0xe5, 0xd7, 0x3c, 0xec, 0xb4, 0xf0, 0x22,
0x38, 0x2d, 0x32, 0x8e, 0xd3, 0xdf, 0x09, 0x9c, 0x72, 0x03, 0x00,
0x78, 0x06, 0xe2, 0xe8, 0xfc, 0x54, 0x08, 0x7c, 0xa0, 0x72, 0x5c,
0x96, 0x73, 0x02, 0x69, 0x40, 0xe3, 0x8f, 0xe8, 0x68, 0xad, 0x37,
0x82, 0x5b, 0xdc, 0xdc, 0x2c, 0xee, 0x08, 0x83, 0xea, 0x8c, 0x1e,
0x83, 0x89, 0x6f, 0xfc, 0x69, 0xb7, 0xfc, 0xf3, 0x9c, 0xe2, 0x29,
0xd9, 0x4a, 0xa9, 0x58, 0x1a, 0xe6, 0xfd, 0x46, 0xbe, 0x3a, 0x95,
0x5f, 0xfd, 0x57, 0xb8, 0x42, 0x4a, 0xdc, 0x88, 0xad, 0x7d, 0x06,
0xbf, 0x4a, 0xe0, 0xd2, 0xea, 0xcf, 0x05, 0x6b, 0x45, 0xe7, 0x92,
0x67, 0x77, 0x1f, 0xcf, 0xff, 0x6a, 0x71, 0x7a, 0x2f, 0x68, 0xb6,
0x6b, 0x4a, 0xb6, 0x3b, 0xd0, 0x3d, 0x26, 0x38, 0xf4, 0xed, 0x56,
0xbb, 0x35, 0xcd, 0xb8, 0xf8, 0x9f, 0x27, 0x6c, 0x93, 0x20, 0x84,
0x0e, 0x48, 0xde, 0x1d, 0x8e, 0x2f, 0x81, 0x17, 0x2f, 0xc5, 0xee,
0x6a, 0x52, 0x42, 0x16, 0xca, 0x32, 0x8c, 0xef, 0x17, 0xde, 0x6e,
0x41, 0x61, 0x2e, 0xcc, 0x35, 0x76, 0x62, 0x1f, 0x90, 0xd9, 0x4b,
0xfc, 0xb4, 0x72, 0xcc, 0x3d, 0x2c, 0x5b, 0x14, 0x72, 0xe1, 0x99,
0xc6, 0x6c, 0x04, 0xc0, 0x3a, 0xef, 0x01, 0xc7, 0x15, 0xea, 0xdb,
0x62, 0x17, 0x9d, 0xb4, 0xe3, 0xbb, 0x83, 0x05, 0x6e, 0x1b, 0x30,
0x89, 0x80, 0x56, 0x48, 0x66, 0x9c, 0xea, 0x99, 0x0e, 0x40, 0xda,
0x44, 0xb8, 0x61, 0xa7, 0x0c, 0xa4, 0xc3, 0xa9, 0x15, 0x5d, 0xdc,
0x80, 0x5b, 0x42, 0x0b, 0x9e, 0xd1, 0xb1, 0x40, 0x36, 0xf1, 0x41,
0x1b, 0x4d, 0x4d, 0x70, 0xc5, 0x42, 0xaa, 0x31, 0xaf, 0xfe, 0x2c,
0xfd, 0x28, 0x76, 0x52, 0xfa, 0x31, 0x98, 0x94, 0x7e, 0x76, 0x25,
0x0f, 0x89, 0x88, 0x0e, 0xfd, 0xc5, 0x50, 0x60, 0x43, 0x99, 0xfa,
0xfa, 0x99, 0x86, 0x3f, 0xa6, 0x4a, 0xbb, 0x7d, 0xf5, 0xfa, 0x8a,
0xf3, 0xe9, 0x1b, 0x04, 0xd3, 0xf9, 0x4e, 0x40, 0x5b, 0x9a, 0xf7,
0x0c, 0x55, 0x4d, 0xe8, 0x3c, 0x75, 0x34, 0x00, 0x6c, 0x19, 0xb9,
0x59, 0x2c, 0xb8, 0xd0, 0xcd, 0x4a, 0x03, 0xa4, 0x61, 0x97, 0xe7,
0xfa, 0xcd, 0x83, 0x8e, 0x62, 0xc7, 0x47, 0xd3, 0x57, 0xd3, 0x04,
0x51, 0x54, 0xc1, 0x79, 0x89, 0x0a, 0x87, 0xfd, 0x18, 0xd1, 0x35,
0xdc, 0x9a, 0xc8, 0x28, 0x9d, 0x4b, 0x14, 0x87, 0x2b, 0x83, 0xf3,
0x82, 0x8b, 0x03, 0x23, 0x6a, 0x27, 0xc0, 0xc0, 0x82, 0x51, 0xd3,
0xc9, 0x95, 0x3c, 0x88, 0x8d, 0x63, 0x54, 0x7f, 0x13, 0xcb, 0xbc,
0xac, 0xa7, 0xe4, 0x7a, 0xe0, 0xc6, 0xfa, 0x70, 0x2b, 0x8c, 0x3f,
0x6c, 0x49, 0xef, 0x64, 0x91, 0xc4, 0x69, 0xc1, 0xf2, 0x4a, 0x5a,
0x44, 0x40, 0x1f, 0x6a, 0x07, 0x70, 0x3d, 0xc7, 0xf2, 0x44, 0x30,
0xae, 0x38, 0xcc, 0x76, 0xc2, 0x4b, 0xfb, 0xd8, 0xa1, 0x2f, 0x34,
0xcf, 0x44, 0x7c, 0xc5, 0xe2, 0x74, 0x61, 0x98, 0xb0, 0x70, 0x11,
0x00, 0xe2, 0x32, 0xc7, 0x1d, 0x0f, 0x96, 0x7c, 0x4c, 0xe3, 0x0e,
0x51, 0xc7, 0x81, 0x0c, 0xe2, 0xe8, 0x79, 0x89, 0x36, 0x52, 0xa2,
0xef, 0x29, 0x0e, 0xa6, 0x26, 0x26, 0x57, 0xe2, 0xc7, 0x5f, 0x9d,
0x9c, 0x48, 0x6d, 0x01, 0x02, 0x5b, 0x4f, 0x94, 0x22, 0x80, 0xd7,
0xb3, 0x74, 0x0d, 0xcb, 0xd1, 0x70, 0x5e, 0xbb, 0x48, 0x97, 0xe5,
0xc1, 0x07, 0x81, 0xcf, 0x04, 0xe1, 0xfc, 0x6b, 0x60, 0xf3, 0x71,
0xb8, 0xe0, 0xfd, 0x16, 0xd1, 0x7b, 0x44, 0xf9, 0x42, 0x71, 0xb8,
0x96, 0x46, 0x4e, 0x11, 0x6c, 0x50, 0x97, 0x3c, 0x02, 0x3f, 0x66,
0x5b, 0xc9, 0xf5, 0xe2, 0x81, 0x7c, 0x42, 0xd9, 0x95, 0xe6, 0x43,
0x09, 0xc5, 0x65, 0x24, 0xc9, 0x76, 0x43, 0x78, 0xc0, 0x1e, 0xb1,
0x4b, 0x6e, 0xba, 0x2f, 0xa6, 0x00, 0x6c, 0xdf, 0xf1, 0xd0, 0x5e,
0x35, 0x8e, 0xb9, 0x05, 0x52, 0x0d, 0xcd, 0xf6, 0x36, 0xab, 0x61,
0x2e, 0xb2, 0x69, 0xfb, 0x1c, 0x1f, 0x05, 0xd0, 0x9a, 0xf2, 0xb7,
0xef, 0xa0, 0xfc, 0x2d, 0x48, 0x79, 0x60, 0x96, 0x5b, 0x46, 0x5b,
0x95, 0xde, 0x39, 0x26, 0x29, 0xe3, 0xc3, 0x54, 0x9e, 0x6e, 0x61,
0x8f, 0x39, 0x25, 0x4d, 0x93, 0x21, 0x1b, 0x92, 0x2c, 0xca, 0xba,
0x0b, 0x81, 0x22, 0x54, 0x1c, 0x5e, 0xe8, 0x81, 0x7a, 0xa4, 0x9a,
0x1c, 0x96, 0x68, 0xf8, 0xf1, 0x8b, 0xee, 0xe3, 0x1a, 0x57, 0xc8,
0xd9, 0x90, 0xe3, 0xb4, 0xe6, 0x68, 0x89, 0xab, 0x33, 0xd8, 0xd5,
0xb8, 0x03, 0x0d, 0x38, 0x50, 0xcf, 0x26, 0x13, 0x50, 0x52, 0x6d,
0x94, 0x1d, 0xc6, 0xa0, 0xd6, 0xb9, 0x7a, 0xb6, 0xe8, 0x4a, 0xde,
0xd9, 0xa6, 0x2b, 0x2d, 0x89, 0xfb, 0x2c, 0x1c, 0xd3, 0x73, 0x20,
0xf2, 0xc7, 0xe7, 0x2a, 0x8d, 0x94, 0xff, 0xc8, 0x1f, 0x4d, 0xc0,
0x97, 0x30, 0x63, 0x88, 0x17, 0x92, 0xce, 0x66, 0x3d, 0xc6, 0x1c,
0xe1, 0x3b, 0x82, 0xd7, 0x8c, 0xd9, 0x2a, 0x24, 0xc0, 0x9e, 0xd4,
0x80, 0x2b, 0x9c, 0x49, 0x2f, 0x04, 0x3b, 0x2c, 0x78, 0x46, 0xef,
0xb1, 0xd0, 0xe9, 0x4e, 0xe8, 0xcd, 0x85, 0xea, 0xea, 0xed, 0xb9,
0xe2, 0x04, 0x0c, 0x72, 0xa2, 0x0b, 0xb2, 0x0c, 0x45, 0x01, 0x5d,
0xfc, 0x79, 0xfe, 0x2d, 0xe2, 0xd9, 0x4d, 0xf5, 0x4b, 0x96, 0xb3,
0x5d, 0xed, 0xac, 0x7e, 0x78, 0x75, 0x79, 0x7d, 0x7e, 0x72, 0xe7,
0x35, 0x4b, 0xac, 0x2e, 0x37, 0xbc, 0xa0, 0x99, 0xe3, 0x92, 0x7b,
0xf7, 0x3b, 0x11, 0xaf, 0x9c, 0x60, 0x99, 0xec, 0x0d, 0x8c, 0xaf,
0x41, 0x2f, 0x78, 0x3d, 0x9e, 0xb1, 0x5d, 0xe9, 0x66, 0xb8, 0x1d,
0xbf, 0x70, 0x8d, 0x4b, 0x15, 0x57, 0x0e, 0xb3, 0xf3, 0xbb, 0xcb,
0x8b, 0x43, 0x07, 0xa3, 0xa9, 0xae, 0xb8, 0x4e, 0xbf, 0x71, 0x22,
0xc2, 0x6f, 0xf7, 0xa4, 0x6e, 0x6b, 0xef, 0x3f, 0xdb, 0x86, 0xe1,
0x85, 0x26, 0x73, 0x7a, 0xfe, 0xfe, 0xf2, 0xfa, 0xd0, 0x5f, 0xaa,
0xe4, 0xdb, 0x6b, 0xe1, 0x52, 0xca, 0xe6, 0x30, 0xb0, 0x8c, 0x68,
0x08, 0xcc, 0xc8, 0x9d, 0xf4, 0x9b, 0xbd, 0x65, 0xac, 0xa8, 0x9a,
0xae, 0x08, 0x9a, 0x38, 0x6e, 0xa9, 0xfb, 0xdc, 0x71, 0x31, 0x7d,
0x80, 0x66, 0xa1, 0x91, 0x62, 0xd0, 0x8a, 0xb9, 0xbd, 0x3a, 0xe9,
0xf3, 0xa9, 0xf9, 0x10, 0x9d, 0x23, 0x72, 0xaa, 0x32, 0x4a, 0x3f,
0x9d, 0x7b, 0x4f, 0x49, 0x5b, 0xc7, 0xab, 0xf9, 0x11, 0xc5, 0xe7,
0xb8, 0xda, 0xd3, 0x29, 0x3d, 0xe3, 0x75, 0xb9, 0x53, 0x47, 0x26,
0x4b, 0x48, 0xa7, 0x82, 0x0c, 0xd7, 0xe2, 0x97, 0x6b, 0xae, 0x98,
0x99, 0xee, 0x2a, 0x06, 0x8a, 0x8a, 0x41, 0xb3, 0x2c, 0x11, 0xcb,
0x28, 0xaa, 0x11, 0x64, 0x59, 0x3a, 0x82, 0x29, 0xd0, 0x2c, 0x20,
0xde, 0x4b, 0x9e, 0x2a, 0x6f, 0xf9, 0xba, 0x30, 0x47, 0x19, 0x4f,
0x1e, 0xfd, 0x32, 0x9f, 0x33, 0xa3, 0xa2, 0x8f, 0x8c, 0x05, 0xaa,
0xd2, 0xe4, 0xaf, 0xec, 0x81, 0xf1, 0x14, 0x62, 0x3f, 0x4c, 0x85,
0xe1, 0xfd, 0x38, 0x93, 0x94, 0x58, 0x64, 0xaf, 0xb5, 0x68, 0x72,
0x97, 0x71, 0x89, 0x91, 0x03, 0xef, 0xa5, 0x39, 0xfb, 0xe0, 0xe3,
0xf2, 0x28, 0x0b, 0x1f, 0x97, 0x47, 0x59, 0x05, 0x8d, 0xcb, 0xa3,
0xac, 0x50, 0x3a, 0x35, 0x98, 0x4f, 0x7c, 0x03, 0xe9, 0x68, 0x8f,
0x4a, 0xba, 0x1c, 0xf8, 0x20, 0x26, 0xee, 0x63, 0xc5, 0x28, 0x26,
0xc9, 0x8a, 0x72, 0x18, 0x23, 0x12, 0x3a, 0x4b, 0xd8, 0x31, 0x8e,
0xfd, 0x7b, 0x1c, 0x97, 0xd0, 0x59, 0xf8, 0xb8, 0x84, 0xce, 0xb2,
0xd2, 0xb3, 0x3f, 0xc3, 0x4a, 0xe8, 0x14, 0x5d, 0xf1, 0x38, 0x28,
0x4f, 0xd1, 0xe3, 0x1f, 0xa2, 0xbf, 0xd4, 0xe4, 0x7f, 0x9e, 0x95,
0x25, 0xcd, 0x66, 0x20, 0xd2, 0x12, 0x57, 0x63, 0x7c, 0x63, 0x90,
0xaf, 0x50, 0xe7, 0x6f, 0x74, 0xd3, 0x2f, 0xec, 0xb2, 0xaf, 0x6e,
0xde, 0x85, 0xb8, 0x51, 0xa2, 0xe5, 0xf5, 0x1d, 0xd2, 0x8d, 0x7a,
0x10, 0x5b, 0x22, 0x37, 0x0d, 0xc8, 0x20, 0x23, 0xa6, 0x92, 0xa1,
0x2a, 0x29, 0x51, 0x94, 0x7a, 0x0c, 0x7c, 0x30, 0x13, 0xab, 0xef,
0x29, 0xa1, 0x8f, 0x02, 0xad, 0x0a, 0x95, 0x69, 0x15, 0x78, 0xb1,
0x68, 0x1b, 0xd4, 0xf5, 0xdc, 0x39, 0xf8, 0x8d, 0xf9, 0x1b, 0x7b,
0x09, 0xad, 0x71, 0xd3, 0xe0, 0x8d, 0xf3, 0x96, 0xd9, 0x4c, 0x90,
0xa1, 0x66, 0x85, 0x2b, 0xae, 0xc5, 0xa6, 0xb1, 0x06, 0x90, 0x60,
0x48, 0x8c, 0x4b, 0xdb, 0x12, 0xd2, 0x91, 0xb4, 0x99, 0x98, 0xaf,
0xd5, 0x90, 0x87, 0xec, 0x5c, 0xd7, 0xe9, 0xc7, 0x03, 0x79, 0x91,
0x0d, 0x8e, 0xc7, 0xd8, 0xd0, 0xe8, 0x2c, 0x38, 0x38, 0x73, 0xb2,
0x1d, 0x84, 0xb4, 0xba, 0x02, 0xf9, 0xa8, 0x3f, 0x30, 0x0b, 0x70,
0xee, 0x0f, 0xcb, 0x02, 0xd3, 0x02, 0xcf, 0xbe, 0x47, 0x44, 0xff,
0xc8, 0x79, 0xf3, 0x12, 0x80, 0x0e, 0x37, 0x48, 0x68, 0xf5, 0x1e,
0xf7, 0xcd, 0xdc, 0xf6, 0x4c, 0xdc, 0xae, 0xe1, 0x06, 0x2f, 0x25,
0x81, 0xcb, 0x6a, 0x41, 0x7e, 0x64, 0xea, 0x06, 0x37, 0x90, 0x4b,
0xd2, 0xe9, 0xc2, 0x7f, 0x16, 0xa6, 0xf3, 0x92, 0x57, 0x4d, 0x47,
0xaf, 0x78, 0x5d, 0x71, 0xf4, 0xfa, 0x25, 0x88, 0xcf, 0x06, 0x56,
0x08, 0x16, 0xa5, 0xdb, 0x0f, 0x48, 0x36, 0xe2, 0x1c, 0xbd, 0x6a,
0xed, 0x1e, 0xf9, 0x9d, 0xa7, 0x6e, 0xec, 0xd5, 0xab, 0x36, 0xf8,
0x73, 0xf8, 0xe9, 0xe4, 0xea, 0xdf, 0xfe, 0xd4, 0x3c, 0x50, 0x6f,
0x5c, 0xe1, 0x35, 0x66, 0xb2, 0x0e, 0x07, 0x09, 0xb9, 0x06, 0x2a,
0x8a, 0x6b, 0x95, 0x7c, 0x44, 0x9b, 0xcf, 0x1b, 0x5e, 0x6f, 0x8a,
0x56, 0xe7, 0x97, 0xd0, 0x6b, 0xff, 0xa8, 0xc6, 0xf3, 0x4d, 0x57,
0xcd, 0x8e, 0xe3, 0x5b, 0xdb, 0xd2, 0x3e, 0xd6, 0xf9, 0x93, 0xe6,
0xde, 0xd6, 0xd3, 0xe9, 0xc9, 0x86, 0x85, 0x25, 0xf6, 0x70, 0x8b,
0xb7, 0xa8, 0x4c, 0xf8, 0x1d, 0x99, 0xfb, 0x73, 0x4d, 0xaf, 0x75,
0x6d, 0x16, 0x1d, 0x47, 0xfd, 0xe0, 0x19, 0xef, 0x33, 0xc5, 0xab,
0x41, 0xb4, 0xaf, 0x25, 0xee, 0xf4, 0xc3, 0x23, 0x47, 0x46, 0xe1,
0x9c, 0x16, 0x77, 0x04, 0xa7, 0x1a, 0x0e, 0x6b, 0xb8, 0xbd, 0x25,
0x8d, 0xbc, 0x68, 0x63, 0x27, 0x68, 0x61, 0x20, 0xae, 0x2c, 0x30,
0xe8, 0xf2, 0x95, 0xe1, 0x38, 0x1d, 0xee, 0x2e, 0x36, 0x84, 0x8e,
0x51, 0xbc, 0xc7, 0xad, 0x08, 0x05, 0xba, 0xd6, 0x71, 0x64, 0xd5,
0x94, 0x7d, 0x9f, 0xd8, 0x17, 0xac, 0xa0, 0xf2, 0x28, 0xad, 0x6d,
0xb5, 0x20, 0x64, 0x1c, 0xd4, 0x3a, 0xfd, 0x1c, 0xd9, 0x42, 0x09,
0x88, 0x24, 0xd9, 0x09, 0x8f, 0xba, 0xa3, 0x40, 0x6b, 0x3b, 0xc6,
0x49, 0x49, 0x72, 0xd8, 0x6b, 0x9a, 0xc7, 0xe2, 0x71, 0xba, 0x11,
0x1e, 0x61, 0xc4, 0x4c, 0x80, 0x1c, 0xc6, 0x8f, 0x8f, 0x03, 0xa2,
0xb5, 0xf9, 0xf4, 0xbe, 0x0c, 0x78, 0x6c, 0xea, 0xeb, 0x5f, 0xc6,
0x31, 0xa6, 0xf7, 0xeb, 0x78, 0xca, 0x6c, 0xbf, 0xa7, 0xbc, 0xa5,
0x64, 0x2b, 0xe2, 0xc9, 0x2e, 0x7e, 0xa8, 0x6d, 0x83, 0xce, 0x66,
0x9e, 0x71, 0x1d, 0x76, 0xcd, 0x3c, 0x67, 0xf0, 0x9d, 0xd4, 0x37,
0x08, 0xfb, 0x81, 0xef, 0x9e, 0x3a, 0xd9, 0x95, 0x6b, 0xad, 0x86,
0xf8, 0x91, 0x0c, 0x35, 0x3d, 0xe3, 0x68, 0x7b, 0x1d, 0x49, 0xee,
0x5e, 0xce, 0xdb, 0x13, 0x98, 0x2d, 0x66, 0xfe, 0x48, 0x3e, 0xcb,
0x21, 0x4f, 0x48, 0x7f, 0x96, 0x5d, 0x58, 0x4c, 0xc2, 0x2e, 0x14,
0x26, 0x61, 0x17, 0x99, 0xbc, 0x31, 0x36, 0xae, 0x6e, 0x12, 0x7c,
0x80, 0x50, 0xc1, 0xa2, 0xd5, 0xa6, 0xe6, 0x66, 0x7c, 0xf1, 0x5a,
0xac, 0x6f, 0xb2, 0xe3, 0x30, 0x76, 0xdd, 0x36, 0xec, 0x5c, 0xf0,
0x25, 0xc6, 0xe4, 0x1a, 0xdb, 0x67, 0x6c, 0x05, 0xeb, 0x7e, 0x4b,
0x54, 0x1e, 0x4d, 0xd8, 0x5d, 0xd5, 0xeb, 0x55, 0xa3, 0xfa, 0xe3,
0x25, 0x22, 0x6b, 0xc4, 0xe8, 0x2e, 0x78, 0x70, 0xb3, 0xee, 0x6e,
0x57, 0xd0, 0x9a, 0xfb, 0x73, 0x3f, 0xd9, 0x18, 0x8f, 0xa6, 0x69,
0x7d, 0xc7, 0x18, 0x75, 0x8a, 0x03, 0xaf, 0x98, 0xac, 0x50, 0x44,
0xfc, 0x13, 0x77, 0xd0, 0xac, 0x7f, 0x4b, 0x01, 0x2f, 0xc4, 0x35,
0xae, 0xfd, 0x40, 0x5c, 0xb9, 0x14, 0x53, 0x38, 0x97, 0x60, 0x14,
0x57, 0x53, 0xcc, 0xcf, 0x12, 0xb3, 0x05, 0x54, 0x6c, 0x2e, 0xd8,
0x90, 0x96, 0xe6, 0xd6, 0x2f, 0x24, 0x67, 0x82, 0xbc, 0x26, 0x63,
0xbc, 0x4a, 0xd5, 0x6e, 0xc4, 0xcf, 0x44, 0xb2, 0x7a, 0x85, 0x68,
0xdf, 0x10, 0xfa, 0x11, 0x61, 0x12, 0xc2, 0x3f, 0xc6, 0x34, 0x7f,
0xfc, 0x88, 0xbe, 0x73, 0x34, 0xce, 0x4c, 0xbd, 0x0b, 0xc4, 0xbf,
0xc4, 0x64, 0x3d, 0xab, 0xc9, 0xdf, 0x92, 0x77, 0x28, 0xd2, 0x73,
0x04, 0xd7, 0x9f, 0x70, 0xc1, 0xec, 0x3d, 0x52, 0x5e, 0x35, 0xbd,
0x7c, 0x7d, 0xfc, 0xfa, 0xed, 0xab, 0xc7, 0xca, 0x54, 0xf2, 0x96,
0x71, 0x6d, 0xf6, 0x9a, 0x85, 0x47, 0xaf, 0xdf, 0xbc, 0x7c, 0xf1,
0xf6, 0x4d, 0x74, 0x0f, 0x8f, 0x31, 0xe7, 0x8f, 0x12, 0x8f, 0xa4,
0x43, 0xa1, 0x17, 0x52, 0x09, 0xd1, 0x0f, 0xe4, 0x43, 0xd9, 0x57,
0x79, 0x71, 0x37, 0x70, 0x63, 0xd8, 0x99, 0x62, 0x10, 0x9c, 0xc7,
0xae, 0x5a, 0x82, 0x6e, 0x94, 0xfc, 0x75, 0x85, 0xf3, 0x95, 0x1c,
0x89, 0x78, 0x7d, 0x2e, 0x51, 0xb9, 0x04, 0xd6, 0xf8, 0xd0, 0xcd,
0x74, 0xa8, 0x9e, 0xf9, 0x04, 0xdb, 0x81, 0xda, 0x61, 0x2c, 0xec,
0x10, 0x2c, 0xd2, 0x63, 0xd4, 0x0e, 0xa8, 0x44, 0xd5, 0x52, 0x19,
0x51, 0xa2, 0x6f, 0x2c, 0xfc, 0xe3, 0xf9, 0x96, 0xeb, 0x8a, 0xc9,
0x21, 0xb6, 0xc7, 0x2e, 0x2f, 0xb4, 0xf6, 0xde, 0xd1, 0x9a, 0x9a,
0x3b, 0x5a, 0xc3, 0x2a, 0x79, 0x36, 0xbc, 0xae, 0x1d, 0x8e, 0x27,
0xd3, 0xc5, 0x30, 0x8d, 0x8a, 0x6a, 0x92, 0x74, 0xe3, 0xd8, 0x70,
0xa6, 0xc5, 0x69, 0xb9, 0x83, 0xd8, 0xd8, 0xcd, 0x95, 0x69, 0xaf,
0xfc, 0x90, 0x4b, 0xf6, 0x39, 0xe7, 0xf9, 0x4a, 0xdc, 0x2f, 0x9a,
0xeb, 0x86, 0xbb, 0xbc, 0x54, 0x97, 0xcf, 0x78, 0x70, 0x0e, 0x2d,
0xa4, 0xdd, 0x97, 0x9b, 0xcb, 0xa5, 0xab, 0xbf, 0xfe, 0x65, 0xf3,
0x58, 0xd3, 0x2c, 0x74, 0x81, 0x7c, 0x5c, 0x4b, 0x0c, 0x80, 0x90,
0x97, 0x75, 0xb7, 0x13, 0xce, 0xe5, 0xb4, 0xad, 0x98, 0x1c, 0x6c,
0x7c, 0x0b, 0x2b, 0xb6, 0x16, 0xf3, 0xf2, 0xc1, 0x19, 0x69, 0xf3,
0xd5, 0xbe, 0x50, 0x64, 0x24, 0x19, 0xce, 0x88, 0x95, 0x33, 0x59,
0x61, 0xa6, 0xba, 0x33, 0xfb, 0x02, 0x01, 0x07, 0xee, 0xaf, 0x53,
0xa7, 0x12, 0x37, 0xd3, 0x63, 0x8a, 0x7d, 0x1b, 0x8f, 0xef, 0xdb,
0x7c, 0x7e, 0xb3, 0x41, 0x34, 0x26, 0x15, 0x26, 0x44, 0xe0, 0x67,
0xca, 0x83, 0xe3, 0x13, 0xbc, 0x04, 0x0c, 0xc6, 0xdd, 0x15, 0x06,
0xa3, 0xaf, 0x5f, 0x83, 0x7e, 0x69, 0x63, 0x0e, 0x66, 0xe2, 0x0a,
0x36, 0xf0, 0xef, 0x18, 0x07, 0x2f, 0x19, 0x77, 0x57, 0xba, 0xdd,
0xd3, 0x6c, 0x17, 0x98, 0xc4, 0x4e, 0xb6, 0xe6, 0x2a, 0x74, 0xcd,
0x22, 0x74, 0xf6, 0xba, 0x65, 0xe4, 0x1b, 0x4e, 0xf7, 0x6b, 0xd4,
0x32, 0xae, 0x77, 0xe8, 0x6d, 0x3e, 0x3c, 0xe2, 0x00, 0xfe, 0x45,
0xe8, 0x71, 0x6f, 0xb8, 0x97, 0xa1, 0x23, 0xd3, 0x91, 0x7b, 0x8c,
0xbe, 0x6a, 0xff, 0x1a, 0x6d, 0xfa, 0xc6, 0xdb, 0xbe, 0x4e, 0x37,
0x4f, 0x32, 0x72, 0xb3, 0x10, 0xf4, 0x24, 0x7f, 0x3a, 0xe6, 0x27,
0xb2, 0xb9, 0x3f, 0xdb, 0x75, 0xe0, 0xaa, 0x4c, 0x34, 0xa3, 0xeb,
0xdf, 0x97, 0x19, 0x21, 0x66, 0x53, 0x97, 0xba, 0xfa, 0x0f, 0x88,
0x2c, 0x33, 0x71, 0x71, 0xf0, 0x2b, 0x55, 0xea, 0xf7, 0x76, 0x22,
0x65, 0xa7, 0x10, 0x46, 0xd8, 0x9b, 0x39, 0x59, 0x65, 0xa0, 0x23,
0x7c, 0x6f, 0x9b, 0xca, 0xfb, 0xca, 0x7f, 0x6f, 0xea, 0x94, 0xee,
0xe8, 0x45, 0xdb, 0x79, 0xf6, 0xf7, 0x04, 0x40, 0xb4, 0xf7, 0xa6,
0x76, 0xb5, 0xb7, 0xda, 0xb6, 0xa5, 0xf6, 0x3e, 0xff, 0xd4, 0xdb,
0xf1, 0x27, 0x42, 0xcb, 0xc2, 0x4e, 0x15, 0x16, 0xfd, 0x9a, 0x16,
0x8b, 0x9f, 0xbb, 0x19, 0x84, 0x55, 0x07, 0xc3, 0x8c, 0x9f, 0x44,
0xae, 0x03, 0x4d, 0xec, 0x7f, 0x09, 0x6f, 0xb6, 0x7d
};
const int standard_nodes_data_len = 2847;

View File

@ -0,0 +1,52 @@
// Filename: standard_nodes.cxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "standard_nodes.h"
// The binary data included here was generated from standardNodes.wrl
// (in this directory) file via the utility program bin2c (defined in
// pandatool). It contains the set of VRML definitions that must be
// loaded before any standard VRML file can be properly interpreted.
#ifndef CPPPARSER
#if defined(HAVE_ZLIB)
// If we have zlib available, we can store this file compressed, which
// is much smaller.
// Regenerate this file with:
// pcompress standardNodes.wrl standardNodes.wrl.pz
// bin2c -n standard_nodes_data -o standardNodes.wrl.pz.c standardNodes.wrl.pz
#include "standardNodes.wrl.pz.c"
#else // HAVE_ZLIB
// If we don't have zlib, just include the whole uncompressed file.
// Regenerate this file with:
// bin2c -n standard_nodes_data -o standardNodes.wrl.c standardNodes.wrl
#include "standardNodes.wrl.c"
#endif // HAVE_ZLIB
#endif // CPPPARSER

View File

@ -0,0 +1,32 @@
// Filename: standard_nodes.h
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef STANDARD_NODES_H
#define STANDARD_NODES_H
#include "pandatoolbase.h"
#ifndef CPPPARSER
extern const unsigned char standard_nodes_data[];
extern const int standard_nodes_data_len;
#endif // CPPPARSER
#endif

View File

@ -0,0 +1,436 @@
// 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;
}

View File

@ -0,0 +1,78 @@
// Filename: vrml2egg.h
// 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.
////////////////////////////////////////////////////////////////////
#ifndef VRML2EGG_H
#define VRML2EGG_H
#include <eggBase.h>
#include <mstring.h>
#include <map.h>
class VrmlNode;
struct SFNodeRef;
class EggGroup;
class pfMatrix;
////////////////////////////////////////////////////////////////////
// Class : MainProgram
// Description : The vrml2egg program class. This handles the user
// input and gets things going.
////////////////////////////////////////////////////////////////////
class MainProgram : public EggBase {
public:
MainProgram() : EggBase("") {
}
virtual void Help();
virtual void Usage();
virtual void ShowOpts();
virtual boolean
HandleGetopts(char flag, char *optarg, int &optind,
int argc, char **argv);
virtual boolean
HandleArgs(int &argc, char **&argv);
void vrml_group(const VrmlNode *node, EggGroup *group,
const pfMatrix &net_transform);
void vrml_transform(const VrmlNode *node, EggGroup *group,
const pfMatrix &net_transform);
void vrml_shape(const VrmlNode *node, EggGroup *group,
const pfMatrix &net_transform);
void 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));
void vrml_node(const SFNodeRef &vrml,
EggGroup *egg, const pfMatrix &net_transform);
typedef map<String, VrmlNode *> Nodes;
void get_all_defs(SFNodeRef &vrml, Nodes &nodes);
void DoIt();
typedef map<const VrmlNode *, EggGroup *> Instances;
Instances _instances;
string _filename;
};
#endif

View File

@ -0,0 +1,574 @@
/*
// Filename: vrmlLexer.lxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
*/
/**************************************************
* VRML 2.0 Parser
* Copyright (C) 1996 Silicon Graphics, Inc.
*
* Author(s) : Gavin Bell
* Daniel Woods (first port)
**************************************************
*/
%{
#include "pandatoolbase.h"
#include "vrmlNode.h"
#include "vrmlParser.h"
#include "indent.h"
#include "notify.h"
static int yyinput(void); // declared by flex.
extern "C" int vrmlyywrap();
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
// We'll increment line_number and col_number as we parse the file, so
// that we can report the position of an error.
static int line_number = 0;
static int col_number = 0;
// current_line holds as much of the current line as will fit. Its
// only purpose is for printing it out to report an error to the user.
static const int max_error_width = 1024;
static char current_line[max_error_width + 1];
static int error_count = 0;
static int warning_count = 0;
// This is the pointer to the current input stream.
static istream *inp = NULL;
// This is the name of the vrml file we're parsing. We keep it so we
// can print it out for error messages.
static string vrml_filename;
int vrmlyy_flex_debug = 0;
extern void vrmlyyerror(const string &);
/* The YACC parser sets this to a token to direct the lexer */
/* in cases where just syntax isn't enough: */
int expectToken = 0;
/* True when parsing a multiple-valued field: */
static int parsing_mf = 0;
/* These are used when parsing SFImage fields: */
static int sfImageIntsParsed = 0;
static int sfImageIntsExpected = 0;
// This is used while scanning a quoted string.
static string quoted_string;
// And this keeps track of the currently-parsing array.
static MFArray *mfarray;
void
vrml_init_lexer(istream &in, const string &filename) {
vrmlyy_flex_debug = 0;
inp = &in;
vrml_filename = filename;
line_number = 0;
col_number = 0;
error_count = 0;
warning_count = 0;
}
////////////////////////////////////////////////////////////////////
// Internal support functions.
////////////////////////////////////////////////////////////////////
int
vrmlyywrap(void) {
return 1;
}
void
vrmlyyerror(const string &msg) {
cerr << "\nError";
if (!vrml_filename.empty()) {
cerr << " in " << vrml_filename;
}
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
error_count++;
}
void
vrmlyywarning(const string &msg) {
cerr << "\nWarning";
if (!vrml_filename.empty()) {
cerr << " in " << vrml_filename;
}
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
warning_count++;
}
// Now define a function to take input from an istream instead of a
// stdio FILE pointer. This is flex-specific.
static void
input_chars(char *buffer, int &result, int max_size) {
nassertv(inp != NULL);
if (*inp) {
inp->read(buffer, max_size);
result = inp->gcount();
if (result >= 0 && result < max_size) {
// Truncate at the end of the read.
buffer[result] = '\0';
}
if (line_number == 0) {
// This is a special case. If we are reading the very first bit
// from the stream, copy it into the current_line array. This
// is because the \n.* rule below, which fills current_line
// normally, doesn't catch the first line.
strncpy(current_line, vrmlyytext, max_error_width);
current_line[max_error_width] = '\0';
line_number++;
col_number = 0;
// Truncate it at the newline.
char *end = strchr(current_line, '\n');
if (end != NULL) {
*end = '\0';
}
}
} else {
// End of file or I/O error.
result = 0;
}
}
#undef YY_INPUT
#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
int extract_int() {
return strtol(yytext, NULL, 0);
}
double extract_float() {
return atof(yytext);
}
void extract_vec(double vec[], int num_elements) {
char *p = yytext;
for (int i = 0; i < num_elements; i++) {
vec[i] = strtod(p, &p);
}
}
%}
/* Normal state: parsing nodes. The initial start state is used */
/* only to recognize the VRML header. */
%x NODE
/* Start tokens for all of the field types, */
/* except for MFNode and SFNode, which are almost completely handled */
/* by the parser: */
%x SFB SFC SFF SFIMG SFI SFR SFS SFT SFV2 SFV3
%x MFC MFF MFI MFR MFS MFV2 MFV3
%x IN_SFS IN_MFS IN_SFIMG
/* Big hairy expression for floating point numbers: */
float (-?(([0-9]+)|([0-9]*\.[0-9]+)([eE][+\-]?[0-9]+)?))
/* Ints are decimal or hex (0x##): */
int (-?([0-9]+)|(0[xX][0-9a-fA-F]*))
/* Whitespace. Using this pattern can screw up currentLineNumber, */
/* so it is only used wherever it is really convenient and it is */
/* extremely unlikely that the user will put in a carriage return */
/* (example: between the floats in an SFVec3f) */
ws ([ \t\r\n,]|(#.*))+
/* And the same pattern without the newline */
wsnnl ([ \t\r,]|(#.*))
/* Legal characters to start an identifier */
idStartChar ([^\x30-\x39\x00-\x20\x22\x23\x27\x2b-\x2e\x5b-\x5d\x7b\x7d])
/* Legal other characters in an identifier */
/*idRestChar ([^\x00-\x20\x22\x23\x27\x2b-\x2e\x5b-\x5d\x7b\x7d])*/
/* Allow hyphen (0x2d) in identifiers. */
idRestChar ([^\x00-\x20\x22\x23\x27\x2b-\x2c\x2e\x5b-\x5d\x7b\x7d])
%%
%{
/* Switch into a new start state if the parser */
/* just told us that we've read a field name */
/* and should expect a field value (or IS) */
if (expectToken != 0) {
if (vrmlyy_flex_debug)
fprintf(stderr,"LEX--> Start State %d\n", expectToken);
/*
* Annoying. This big switch is necessary because
* LEX wants to assign particular numbers to start
* tokens, and YACC wants to define all the tokens
* used, too. Sigh.
*/
switch(expectToken) {
case SFBOOL: BEGIN SFB; break;
case SFCOLOR: BEGIN SFC; break;
case SFFLOAT: BEGIN SFF; break;
case SFIMAGE: BEGIN SFIMG; break;
case SFINT32: BEGIN SFI; break;
case SFROTATION: BEGIN SFR; break;
case SFSTRING: BEGIN SFS; break;
case SFTIME: BEGIN SFT; break;
case SFVEC2F: BEGIN SFV2; break;
case SFVEC3F: BEGIN SFV3; break;
case MFCOLOR: BEGIN MFC; break;
case MFFLOAT: BEGIN MFF; break;
case MFINT32: BEGIN MFI; break;
case MFROTATION: BEGIN MFR; break;
case MFSTRING: BEGIN MFS; break;
case MFVEC2F: BEGIN MFV2; break;
case MFVEC3F: BEGIN MFV3; break;
/* SFNode and MFNode are special. Here the lexer just returns */
/* "marker tokens" so the parser knows what type of field is */
/* being parsed; unlike the other fields, parsing of SFNode/MFNode */
/* field happens in the parser. */
case MFNODE: expectToken = 0; return MFNODE;
case SFNODE: expectToken = 0; return SFNODE;
default: vrmlyyerror("ACK: Bad expectToken"); break;
}
}
%}
/* This is more complicated than they really need to be because */
/* I was ambitious and made the whitespace-matching rule aggressive */
<INITIAL>"#VRML V2.0 utf8".*\n{wsnnl}* {
BEGIN NODE;
}
/* The lexer is in the NODE state when parsing nodes, either */
/* top-level nodes in the .wrl file, in a prototype implementation, */
/* or when parsing the contents of SFNode or MFNode fields. */
<NODE>PROTO { return PROTO; }
<NODE>EXTERNPROTO { return EXTERNPROTO; }
<NODE>DEF { return DEF; }
<NODE>USE { return USE; }
<NODE>TO { return TO; }
<NODE>IS { return IS; }
<NODE>ROUTE { return ROUTE; }
<NODE>NULL { return SFN_NULL; }
<NODE>eventIn { return EVENTIN; }
<NODE>eventOut { return EVENTOUT; }
<NODE>field { return FIELD; }
<NODE>exposedField { return EXPOSEDFIELD; }
/* Legal identifiers: */
<NODE>{idStartChar}{idRestChar}* {
vrmlyylval.string = strdup(yytext);
return IDENTIFIER;
}
/* This hopefully won't bitch things too much. It's not legal for
an identifier to begin with a digit, but Form-Z writes out VRML
files that do. So we'll allow it. Hopefully the start states
will keep them sorted out. */
<NODE>[0-9]{idRestChar}* {
vrmlyylval.string = strdup(yytext);
return IDENTIFIER;
}
/* All fields may have an IS declaration: */
<SFB,SFC,SFF,SFIMG,SFI,SFR,SFS,SFT,SFV2,SFV3>IS {
BEGIN NODE;
expectToken = 0;
yyless(0);
}
<MFC,MFF,MFI,MFR,MFS,MFV2,MFV3>IS {
BEGIN NODE;
expectToken = 0;
yyless(0); /* put back the IS */
}
/* All MF field types other than MFNode are completely parsed here */
/* in the lexer, and one token is returned to the parser. They all */
/* share the same rules for open and closing brackets: */
<MFC,MFF,MFI,MFR,MFS,MFV2,MFV3>\[ {
if (parsing_mf) vrmlyyerror("Double [");
parsing_mf = 1;
mfarray = new MFArray;
}
<MFC,MFF,MFI,MFR,MFS,MFV2,MFV3>\] {
if (!parsing_mf) vrmlyyerror("Unmatched ]");
int fieldType = expectToken;
BEGIN NODE;
parsing_mf = 0;
expectToken = 0;
vrmlyylval.fv._mf = mfarray;
return fieldType;
}
<SFB>TRUE {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sfbool = true;
return SFBOOL;
}
<SFB>FALSE {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sfbool = false;
return SFBOOL;
}
<SFI>{int} {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sfint32 = extract_int();
return SFINT32;
}
<MFI>{int} {
VrmlFieldValue v;
v._sfint32 = extract_int();
if (parsing_mf) {
mfarray->push_back(v);
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFINT32;
}
}
/* All the floating-point types are pretty similar: */
<SFF>{float} {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sffloat = extract_float();
return SFFLOAT;
}
<MFF>{float} {
VrmlFieldValue v;
v._sffloat = extract_float();
if (parsing_mf) {
/* Add to array... */
mfarray->push_back(v);
} else {
/* No open bracket means a single value: */
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFFLOAT;
}
}
<SFV2>{float}{ws}{float} {
BEGIN NODE;
expectToken = 0;
extract_vec(vrmlyylval.fv._sfvec, 2);
return SFVEC2F;
}
<MFV2>{float}{ws}{float} {
VrmlFieldValue v;
extract_vec(v._sfvec, 2);
if (parsing_mf) {
mfarray->push_back(v);
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFVEC2F;
}
}
<SFV3>({float}{ws}){2}{float} {
BEGIN NODE;
expectToken = 0;
extract_vec(vrmlyylval.fv._sfvec, 3);
return SFVEC3F;
}
<MFV3>({float}{ws}){2}{float} {
VrmlFieldValue v;
extract_vec(v._sfvec, 3);
if (parsing_mf) {
mfarray->push_back(v);
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFVEC3F;
}
}
<SFR>({float}{ws}){3}{float} {
BEGIN NODE;
expectToken = 0;
extract_vec(vrmlyylval.fv._sfvec, 4);
return SFROTATION;
}
<MFR>({float}{ws}){3}{float} {
VrmlFieldValue v;
extract_vec(v._sfvec, 4);
if (parsing_mf) {
mfarray->push_back(v);
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFROTATION;
}
}
<SFC>({float}{ws}){2}{float} {
BEGIN NODE;
expectToken = 0;
extract_vec(vrmlyylval.fv._sfvec, 3);
return SFCOLOR;
}
<MFC>({float}{ws}){2}{float} {
VrmlFieldValue v;
extract_vec(v._sfvec, 3);
if (parsing_mf) {
mfarray->push_back(v);
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFCOLOR;
}
}
<SFT>{float} {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sffloat = extract_float();
return SFTIME;
}
/* SFString/MFString */
<SFS>\" {
BEGIN IN_SFS;
quoted_string = "";
}
<MFS>\" {
BEGIN IN_MFS;
quoted_string = "";
}
/* Anything besides open-quote (or whitespace) is an error: */
<SFS>[^ \"\t\r\,\n]+ {
vrmlyyerror("String missing open-quote");
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sfstring = strdup("");
return SFSTRING;
}
/* Expect open-quote, open-bracket, or whitespace: */
<MFS>[^ \[\]\"\t\r\,\n]+ {
vrmlyyerror("String missing open-quote");
BEGIN NODE;
expectToken = 0;
return MFSTRING;
}
/* Backslashed-quotes are OK: */
<IN_SFS,IN_MFS>\\\" {
quoted_string += '"';
}
/* Gobble up anything besides quotes and newlines. */
/* Newlines are legal in strings, but we exclude them here so */
/* that line number are counted correctly by the catch-all newline */
/* rule that applies to everything. */
<IN_SFS,IN_MFS>[^\"\n]+ {
quoted_string += yytext;
}
/* Quote ends the string: */
<IN_SFS>\" {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._sfstring = strdup(quoted_string.c_str());
return SFSTRING;
}
<IN_MFS>\" {
VrmlFieldValue v;
v._sfstring = strdup(quoted_string.c_str());
if (parsing_mf) {
BEGIN MFS;
mfarray->push_back(v);
quoted_string = "";
} else {
BEGIN NODE;
expectToken = 0;
vrmlyylval.fv._mf = new MFArray;
vrmlyylval.fv._mf->push_back(v);
return MFSTRING;
}
}
/* SFImage: width height numComponents then width*height integers: */
<SFIMG>{int}{ws}{int} { int w, h;
sscanf(yytext, "%d %d", &w, &h);
sfImageIntsExpected = 1+w*h;
sfImageIntsParsed = 0;
BEGIN IN_SFIMG;
}
<IN_SFIMG>{int} { ++sfImageIntsParsed;
if (sfImageIntsParsed == sfImageIntsExpected) {
BEGIN NODE; expectToken = 0; return SFIMAGE;
}
}
/* Whitespace and catch-all rules apply to all start states: */
<*>{wsnnl}+ ;
/* This is also whitespace, but we'll keep track of line number */
/* to report in errors: */
<*>{wsnnl}*\n{wsnnl}* ;
/* This catch-all rule catches anything not covered by any of */
/* the above: */
<*>. { return yytext[0]; }

View File

@ -0,0 +1,33 @@
// Filename: vrmlLexerDefs.h
// Created by: drose (30Sep04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VRMLLEXERDEFS_H
#define VRMLLEXERDEFS_H
#include "pandatoolbase.h"
void vrml_init_lexer(istream &in, const string &filename);
int vrml_error_count();
int vrml_warning_count();
void vrmlyyerror(const string &msg);
void vrmlyywarning(const string &msg);
int vrmlyylex();
#endif

View File

@ -0,0 +1,81 @@
// Filename: vrmlNode.cxx
// Created by: drose (23Jun99)
//
////////////////////////////////////////////////////////////////////
// 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 "vrmlNode.h"
#include "vrmlParser.h"
#include "indent.h"
#include "notify.h"
VrmlNode::
VrmlNode(const VrmlNodeType *type) {
_type = type;
_use_count = 0;
}
VrmlNode::
~VrmlNode() {
}
const VrmlFieldValue &VrmlNode::
get_value(const char *field_name) const {
Fields::const_iterator fi;
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
if (strcmp((*fi)._type->name, field_name) == 0) {
return ((*fi)._value);
}
}
// That field was not defined. Get the default value.
const VrmlNodeType::NameTypeRec *field = _type->hasField(field_name);
if (field != NULL) {
return field->dflt;
}
cerr << "No such field defined for type " << _type->getName() << ": "
<< field_name << "\n";
exit(1);
// Just to make the compiler happy.
static VrmlFieldValue zero;
return zero;
}
void VrmlNode::
output(ostream &out, int indent_level) const {
out << _type->getName() << " {\n";
Fields::const_iterator fi;
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
indent(out, indent_level + 2) << (*fi)._type->name << " ";
output_value(out, (*fi)._value, (*fi)._type->type, indent_level + 2) << "\n";
}
indent(out, indent_level) << "}";
}
void Declaration::
output(ostream &out, int indent) const {
VrmlFieldValue v;
v._sfnode = _node;
output_value(out, v, SFNODE, indent);
}
ostream &operator << (ostream &out, const VrmlScene &scene) {
VrmlScene::const_iterator si;
for (si = scene.begin(); si != scene.end(); ++si) {
out << (*si) << "\n";
}
return out;
}

View File

@ -0,0 +1,71 @@
// Filename: vrmlNode.h
// Created by: drose (23Jun99)
//
////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////
#ifndef VRMLNODE_H
#define VRMLNODE_H
#include "pandatoolbase.h"
#include "vrmlNodeType.h"
#include "pvector.h"
#include "pmap.h"
class VrmlNode {
public:
VrmlNode(const VrmlNodeType *type);
~VrmlNode();
const VrmlFieldValue &get_value(const char *field_name) const;
void output(ostream &out, int indent) const;
class Field {
public:
Field() { }
Field(const VrmlNodeType::NameTypeRec *type, const VrmlFieldValue &value) :
_type(type), _value(value) { }
const VrmlNodeType::NameTypeRec *_type;
VrmlFieldValue _value;
};
typedef vector<Field> Fields;
Fields _fields;
int _use_count;
const VrmlNodeType *_type;
};
inline ostream &operator << (ostream &out, const VrmlNode &node) {
node.output(out, 0);
return out;
}
class Declaration {
public:
SFNodeRef _node;
void output(ostream &out, int indent) const;
};
inline ostream &operator << (ostream &out, const Declaration &dec) {
dec.output(out, 0);
return out;
}
typedef pvector<Declaration> VrmlScene;
ostream &operator << (ostream &out, const VrmlScene &scene);
#endif

View File

@ -0,0 +1,333 @@
/**************************************************
* VRML 2.0 Parser
* Copyright (C) 1996 Silicon Graphics, Inc.
*
* Author(s) : Gavin Bell
* Daniel Woods (first port)
**************************************************
*/
//
// The VrmlNodeType class is responsible for storing information about node
// or prototype types.
//
#include "vrmlNodeType.h"
#include "vrmlNode.h"
#include "vrmlParser.h"
#include "notify.h"
#include "indent.h"
//
// Static list of node types.
//
plist<VrmlNodeType*> VrmlNodeType::typeList;
static ostream &
output_array(ostream &out, const MFArray *mf,
int type, int indent_level, int items_per_row) {
if (mf->empty()) {
out << "[ ]";
} else {
out << "[";
MFArray::const_iterator mi;
int col = 0;
for (mi = mf->begin(); mi != mf->end(); ++mi) {
if (col == 0) {
out << "\n";
indent(out, indent_level + 2);
}
output_value(out, (*mi), type, indent_level + 2);
if (++col >= items_per_row) {
col = 0;
} else {
out << " ";
}
}
out << "\n";
indent(out, indent_level) << "]";
}
return out;
}
ostream &
output_value(ostream &out, const VrmlFieldValue &value, int type,
int indent) {
switch (type) {
case SFBOOL:
return out << (value._sfbool ? "TRUE" : "FALSE");
case SFFLOAT:
case SFTIME:
return out << value._sffloat;
case SFINT32:
return out << value._sfint32;
case SFSTRING:
{
out << '"';
for (const char *p = value._sfstring; *p != '\0'; p++) {
if (*p == '"') {
out << "\\\"";
} else {
out << *p;
}
}
return out << '"';
}
case SFVEC2F:
return out << value._sfvec[0] << " " << value._sfvec[1];
case SFCOLOR:
case SFVEC3F:
return out << value._sfvec[0] << " " << value._sfvec[1] << " "
<< value._sfvec[2];
case SFROTATION:
return out << value._sfvec[0] << " " << value._sfvec[1] << " "
<< value._sfvec[2] << " " << value._sfvec[3];
case SFNODE:
switch (value._sfnode._type) {
case SFNodeRef::T_null:
return out << "NULL";
case SFNodeRef::T_unnamed:
nassertr(value._sfnode._p != NULL, out);
value._sfnode._p->output(out, indent);
return out;
case SFNodeRef::T_def:
out << "DEF " << value._sfnode._name << " ";
value._sfnode._p->output(out, indent);
return out;
case SFNodeRef::T_use:
return out << "USE " << value._sfnode._name;
}
return out << "(invalid)";
case SFIMAGE:
return out << "(image)";
case MFCOLOR:
return output_array(out, value._mf, SFCOLOR, indent, 1);
case MFFLOAT:
return output_array(out, value._mf, SFFLOAT, indent, 5);
case MFINT32:
return output_array(out, value._mf, SFINT32, indent, 10);
case MFROTATION:
return output_array(out, value._mf, SFROTATION, indent, 1);
case MFSTRING:
return output_array(out, value._mf, SFSTRING, indent, 1);
case MFVEC2F:
return output_array(out, value._mf, SFVEC2F, indent, 1);
case MFVEC3F:
return output_array(out, value._mf, SFVEC3F, indent, 1);
case MFNODE:
return output_array(out, value._mf, SFNODE, indent, 1);
}
return out << "(unknown)";
}
VrmlNodeType::VrmlNodeType(const char *nm)
{
nassertv(nm != NULL);
name = strdup(nm);
}
VrmlNodeType::~VrmlNodeType()
{
free(name);
// Free strings duplicated when fields/eventIns/eventOuts added:
plist<NameTypeRec*>::iterator i;
for (i = eventIns.begin(); i != eventIns.end(); i++) {
NameTypeRec *r = *i;
free(r->name);
delete r;
}
for (i = eventOuts.begin(); i != eventOuts.end(); i++) {
NameTypeRec *r = *i;
free(r->name);
delete r;
}
for (i = fields.begin(); i != fields.end(); i++) {
NameTypeRec *r = *i;
free(r->name);
delete r;
}
}
void
VrmlNodeType::addToNameSpace(VrmlNodeType *_type)
{
if (find(_type->getName()) != NULL) {
cerr << "PROTO " << _type->getName() << " already defined\n";
return;
}
typeList.push_front(_type);
}
//
// One list is used to store all the node types. Nested namespaces are
// separated by NULL elements.
// This isn't terribly efficient, but it is nice and simple.
//
void
VrmlNodeType::pushNameSpace()
{
typeList.push_front(NULL);
}
void
VrmlNodeType::popNameSpace()
{
// Remove everything up to and including the next NULL marker:
plist<VrmlNodeType*>::iterator i;
for (i = typeList.begin(); i != typeList.end();) {
VrmlNodeType *nodeType = *i;
++i;
typeList.pop_front();
if (nodeType == NULL) {
break;
}
else {
// NOTE: Instead of just deleting the VrmlNodeTypes, you will
// probably want to reference count or garbage collect them, since
// any nodes created as part of the PROTO implementation will
// probably point back to their VrmlNodeType structure.
delete nodeType;
}
}
}
const VrmlNodeType *
VrmlNodeType::find(const char *_name)
{
// Look through the type stack:
plist<VrmlNodeType*>::iterator i;
for (i = typeList.begin(); i != typeList.end(); i++) {
const VrmlNodeType *nt = *i;
if (nt != NULL && strcmp(nt->getName(),_name) == 0) {
return nt;
}
}
return NULL;
}
void
VrmlNodeType::addEventIn(const char *name, int type,
const VrmlFieldValue *dflt)
{
add(eventIns, name, type, dflt);
};
void
VrmlNodeType::addEventOut(const char *name, int type,
const VrmlFieldValue *dflt)
{
add(eventOuts, name, type, dflt);
};
void
VrmlNodeType::addField(const char *name, int type,
const VrmlFieldValue *dflt)
{
add(fields, name, type, dflt);
};
void
VrmlNodeType::addExposedField(const char *name, int type,
const VrmlFieldValue *dflt)
{
char tmp[1000];
add(fields, name, type, dflt);
sprintf(tmp, "set_%s", name);
add(eventIns, tmp, type, dflt);
sprintf(tmp, "%s_changed", name);
add(eventOuts, tmp, type, dflt);
};
void
VrmlNodeType::add(plist<NameTypeRec*> &recs, const char *name, int type,
const VrmlFieldValue *dflt)
{
NameTypeRec *r = new NameTypeRec;
r->name = strdup(name);
r->type = type;
if (dflt != NULL) {
r->dflt = *dflt;
} else {
memset(&r->dflt, 0, sizeof(r->dflt));
}
recs.push_front(r);
}
const VrmlNodeType::NameTypeRec *
VrmlNodeType::hasEventIn(const char *name) const
{
return has(eventIns, name);
}
const VrmlNodeType::NameTypeRec *
VrmlNodeType::hasEventOut(const char *name) const
{
return has(eventOuts, name);
}
const VrmlNodeType::NameTypeRec *
VrmlNodeType::hasField(const char *name) const
{
return has(fields, name);
}
const VrmlNodeType::NameTypeRec *
VrmlNodeType::hasExposedField(const char *name) const
{
// Must have field "name", eventIn "set_name", and eventOut
// "name_changed", all with same type:
char tmp[1000];
const NameTypeRec *base, *set_name, *name_changed;
base = has(fields, name);
sprintf(tmp, "set_%s\n", name);
nassertr(strlen(tmp) < 1000, NULL);
set_name = has(eventIns, tmp);
sprintf(tmp, "%s_changed\n", name);
nassertr(strlen(tmp) < 1000, NULL);
name_changed = has(eventOuts, tmp);
if (base == NULL || set_name == NULL || name_changed == NULL) {
return NULL;
}
if (base->type != set_name->type || base->type != name_changed->type) {
return NULL;
}
return base;
}
const VrmlNodeType::NameTypeRec *
VrmlNodeType::has(const plist<NameTypeRec*> &recs, const char *name) const
{
plist<NameTypeRec*>::const_iterator i;
for (i = recs.begin(); i != recs.end(); i++) {
if (strcmp((*i)->name, name) == 0)
return (*i);
}
return NULL;
}

View File

@ -0,0 +1,108 @@
/**************************************************
* VRML 2.0 Parser
* Copyright (C) 1996 Silicon Graphics, Inc.
*
* Author(s) : Gavin Bell
* Daniel Woods (first port)
**************************************************
*/
#ifndef VRMLNODETYPE_H
#define VRMLNODETYPE_H
//
// The VrmlNodeType class is responsible for storing information about node
// or prototype types.
//
#include "pandatoolbase.h"
#include "plist.h"
#include "pvector.h"
class VrmlNode;
struct SFNodeRef {
VrmlNode *_p;
enum { T_null, T_unnamed, T_def, T_use } _type;
char *_name;
};
union VrmlFieldValue {
bool _sfbool;
double _sffloat;
long _sfint32;
char *_sfstring;
double _sfvec[4];
SFNodeRef _sfnode;
pvector<VrmlFieldValue> *_mf;
};
typedef pvector<VrmlFieldValue> MFArray;
ostream &output_value(ostream &out, const VrmlFieldValue &value, int type,
int indent = 0);
class VrmlNodeType {
public:
// Constructor. Takes name of new type (e.g. "Transform" or "Box")
// Copies the string given as name.
VrmlNodeType(const char *nm);
// Destructor exists mainly to deallocate storage for name
~VrmlNodeType();
// Namespace management functions. PROTO definitions add node types
// to the namespace. PROTO implementations are a separate node
// namespace, and require that any nested PROTOs NOT be available
// outside the PROTO implementation.
// addToNameSpace will print an error to stderr if the given type
// is already defined.
static void addToNameSpace(VrmlNodeType *);
static void pushNameSpace();
static void popNameSpace();
// Find a node type, given its name. Returns NULL if type is not defined.
static const VrmlNodeType *find(const char *nm);
// Routines for adding/getting eventIns/Outs/fields
void addEventIn(const char *name, int type,
const VrmlFieldValue *dflt = NULL);
void addEventOut(const char *name, int type,
const VrmlFieldValue *dflt = NULL);
void addField(const char *name, int type,
const VrmlFieldValue *dflt = NULL);
void addExposedField(const char *name, int type,
const VrmlFieldValue *dflt = NULL);
typedef struct {
char *name;
int type;
VrmlFieldValue dflt;
} NameTypeRec;
const NameTypeRec *hasEventIn(const char *name) const;
const NameTypeRec *hasEventOut(const char *name) const;
const NameTypeRec *hasField(const char *name) const;
const NameTypeRec *hasExposedField(const char *name) const;
const char *getName() const { return name; }
private:
void add(plist<NameTypeRec*> &,const char *,int, const VrmlFieldValue *dflt);
const NameTypeRec *has(const plist<NameTypeRec*> &,const char *) const;
char *name;
// Node types are stored in this data structure:
static plist<VrmlNodeType*> typeList;
plist<NameTypeRec*> eventIns;
plist<NameTypeRec*> eventOuts;
plist<NameTypeRec*> fields;
};
#endif

View File

@ -0,0 +1,570 @@
// Filename: vrmlParser.yxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
// *******************************************************
// VRML 2.0 Parser
// Copyright (C) 1996 Silicon Graphics, Inc.
//
// Author(s) : Gavin Bell
// Daniel Woods (first port, minor fixes)
// *******************************************************
//
%{
//
// Parser for VRML 2.0 files.
// This is a minimal parser that does NOT generate an in-memory scene graph.
//
// The original parser was developed on a Windows 95 PC with
// Borland's C++ 5.0 development tools. This was then ported
// to a Windows 95 PC with Microsoft's MSDEV C++ 4.0 development
// tools. The port introduced the ifdef's for
// USING_BORLAND_CPP_5 : since this provides a "std namespace",
// TWO_ARGUMENTS_FOR_STL_STACK : STL is a moving target. The stack template
// class takes either one or two arguments.
#include "pandatoolbase.h"
#include "vrmlLexerDefs.h"
#include "vrmlNodeType.h"
#include "vrmlNode.h"
#include "notify.h"
#include "plist.h"
#include <stack>
//#define YYDEBUG 1
// Currently-being-define proto. Prototypes may be nested, so a stack
// is needed:
stack< VrmlNodeType*, plist<VrmlNodeType*> > currentProtoStack;
// This is used to keep track of which field in which type of node is being
// parsed. Field are nested (nodes are contained inside MFNode/SFNode fields)
// so a stack of these is needed:
typedef struct {
const VrmlNodeType *nodeType;
const char *fieldName;
const VrmlNodeType::NameTypeRec *typeRec;
} FieldRec;
stack< FieldRec*, plist<FieldRec*> > currentField;
// Similarly for the node entries (which contain the actual values for
// the fields as they are encountered):
stack< VrmlNode*, plist<VrmlNode*> > currentNode;
// This is used when the parser knows what kind of token it expects
// to get next-- used when parsing field values (whose types are declared
// and read by the parser) and at certain other places:
extern int expectToken;
// This is where we store the parsed scene.
VrmlScene *parsed_scene = NULL;
// Some helper routines defined below:
static void beginProto(const char *);
static void endProto();
int addField(const char *type, const char *name, const VrmlFieldValue *dflt = NULL);
int addEventIn(const char *type, const char *name, const VrmlFieldValue *dflt = NULL);
int addEventOut(const char *type, const char *name, const VrmlFieldValue *dflt = NULL);
int addExposedField(const char *type, const char *name, const VrmlFieldValue *dflt = NULL);
int add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *),
const char *typeString, const char *name,
const VrmlFieldValue *dflt);
int fieldType(const char *type);
void enterNode(const char *);
VrmlNode *exitNode();
void inScript();
void enterField(const char *);
void storeField(const VrmlFieldValue &value);
void exitField();
void expect(int type);
extern void vrmlyyerror(const string &);
////////////////////////////////////////////////////////////////////
// Defining the interface to the parser.
////////////////////////////////////////////////////////////////////
void
vrml_init_parser(istream &in, const string &filename) {
//yydebug = 0;
vrml_init_lexer(in, filename);
}
void
vrml_cleanup_parser() {
}
%}
%union {
char *string;
VrmlFieldValue fv;
VrmlNode *node;
MFArray *mfarray;
SFNodeRef nodeRef;
VrmlScene *scene;
};
%type <fv> fieldValue
%type <node> node
%type <nodeRef> nodeDeclaration
%type <mfarray> mfnodeValue nodes
%type <scene> declarations
/*
* And types that will be needed by a true VRML implementation:
* %type <nodeList> vrmlscene declarations
*/
%token <string> IDENTIFIER
%token DEF USE PROTO EXTERNPROTO TO IS ROUTE SFN_NULL
%token EVENTIN EVENTOUT FIELD EXPOSEDFIELD
%token <fv> SFBOOL SFCOLOR SFFLOAT SFIMAGE SFINT32 SFNODE SFROTATION
%token <fv> SFSTRING SFTIME SFVEC2F SFVEC3F
%token <fv> MFCOLOR MFFLOAT MFINT32 MFROTATION MFSTRING MFVEC2F MFVEC3F
%token <fv> MFNODE
%%
vrmlscene: declarations
{
parsed_scene = $1;
}
;
declarations:
/* Empty is OK */
{
$$ = new VrmlScene;
}
| declarations nodeDeclaration
{
Declaration d;
d._node = $2;
$1->push_back(d);
$$ = $1;
}
| declarations protoDeclaration
| declarations routeDeclaration
;
nodeDeclaration:
node
{
$$._p = $1;
$$._type = SFNodeRef::T_unnamed;
$$._name = NULL;
}
| DEF IDENTIFIER node
{
$$._p = $3;
$$._type = SFNodeRef::T_def;
$$._name = $2;
}
| USE IDENTIFIER
{
$$._p = NULL;
$$._type = SFNodeRef::T_use;
$$._name = $2;
}
;
protoDeclaration:
proto
| externproto
;
proto:
PROTO IDENTIFIER { beginProto($2); }
'[' interfaceDeclarations ']'
'{' declarations '}' { endProto(); free($2);}
;
externproto:
EXTERNPROTO IDENTIFIER { beginProto($2); }
'[' externInterfaceDeclarations ']'
{ expect(MFSTRING); }
fieldValue { endProto(); free($2); }
;
interfaceDeclarations:
/* Empty is OK */
| interfaceDeclarations interfaceDeclaration
;
interfaceDeclaration:
EVENTIN IDENTIFIER IDENTIFIER { addEventIn($2, $3);
free($2); free($3); }
| EVENTOUT IDENTIFIER IDENTIFIER { addEventOut($2, $3);
free($2); free($3); }
| FIELD IDENTIFIER IDENTIFIER
{
int type = fieldType($2);
expect(type);
}
fieldValue
{
addField($2, $3, &($5));
free($2);
free($3);
}
| EXPOSEDFIELD IDENTIFIER IDENTIFIER
{
int type = fieldType($2);
expect(type);
}
fieldValue
{
addExposedField($2, $3, &($5));
free($2);
free($3);
}
;
externInterfaceDeclarations:
/* Empty is OK */
| externInterfaceDeclarations externInterfaceDeclaration
;
externInterfaceDeclaration:
EVENTIN IDENTIFIER IDENTIFIER { addEventIn($2, $3);
free($2); free($3); }
| EVENTOUT IDENTIFIER IDENTIFIER { addEventOut($2, $3);
free($2); free($3); }
| FIELD IDENTIFIER IDENTIFIER { addField($2, $3);
free($2); free($3); }
| EXPOSEDFIELD IDENTIFIER IDENTIFIER { addExposedField($2, $3);
free($2); free($3); }
;
routeDeclaration:
ROUTE IDENTIFIER '.' IDENTIFIER TO IDENTIFIER '.' IDENTIFIER
{ free($2); free($4); free($6); free($8); }
;
node:
IDENTIFIER { enterNode($1); }
'{' nodeGuts '}' { $$ = exitNode(); free($1);}
;
nodeGuts:
/* Empty is OK */
| nodeGuts nodeGut
;
nodeGut:
IDENTIFIER { enterField($1); }
fieldValue
{
storeField($3);
exitField();
free($1);
}
| routeDeclaration
| protoDeclaration
/* The following are only valid for Script nodes: */
| EVENTIN IDENTIFIER IDENTIFIER { inScript(); free($2); free($3); }
| EVENTOUT IDENTIFIER IDENTIFIER { inScript(); free($2); free($3); }
| FIELD IDENTIFIER IDENTIFIER { inScript();
int type = fieldType($2);
expect(type); }
fieldValue { free($2); free($3); }
| EVENTIN IDENTIFIER IDENTIFIER IS IDENTIFIER
{ inScript(); free($2); free($3); free($5); }
| EVENTOUT IDENTIFIER IDENTIFIER IS IDENTIFIER
{ inScript(); free($2); free($3); free($5); }
;
fieldValue:
SFBOOL
| SFCOLOR
| MFCOLOR
| SFFLOAT
| MFFLOAT
| SFIMAGE
| SFINT32
| MFINT32
| SFROTATION
| MFROTATION
| SFSTRING
| MFSTRING
| SFTIME
| SFVEC2F
| MFVEC2F
| SFVEC3F
| MFVEC3F
| SFNODE nodeDeclaration { $$._sfnode = $2; }
| SFNODE SFN_NULL
{
$$._sfnode._p = NULL;
$$._sfnode._type = SFNodeRef::T_null;
$$._sfnode._name = NULL;
}
| MFNODE mfnodeValue { $$._mf = $2; }
| IS IDENTIFIER { free($2); }
;
mfnodeValue:
'[' nodes ']'
{
$$ = $2;
}
| nodeDeclaration
{
$$ = new MFArray;
VrmlFieldValue v;
v._sfnode = $1;
$$->push_back(v);
}
;
nodes:
/* Empty is OK */
{
$$ = new MFArray;
}
| nodes nodeDeclaration
{
VrmlFieldValue v;
v._sfnode = $2;
$1->push_back(v);
$$ = $1;
}
;
%%
static void
beginProto(const char *protoName)
{
// Any protos in the implementation are in a local namespace:
VrmlNodeType::pushNameSpace();
VrmlNodeType *t = new VrmlNodeType(protoName);
currentProtoStack.push(t);
}
static void
endProto()
{
// Make any protos defined in implementation unavailable:
VrmlNodeType::popNameSpace();
// Add this proto definition:
if (currentProtoStack.empty()) {
cerr << "Error: Empty PROTO stack!\n";
}
else {
VrmlNodeType *t = currentProtoStack.top();
currentProtoStack.pop();
VrmlNodeType::addToNameSpace(t);
}
}
int
addField(const char *type, const char *name,
const VrmlFieldValue *dflt)
{
return add(&VrmlNodeType::addField, type, name, dflt);
}
int
addEventIn(const char *type, const char *name,
const VrmlFieldValue *dflt)
{
return add(&VrmlNodeType::addEventIn, type, name, dflt);
}
int
addEventOut(const char *type, const char *name,
const VrmlFieldValue *dflt)
{
return add(&VrmlNodeType::addEventOut, type, name, dflt);
}
int
addExposedField(const char *type, const char *name,
const VrmlFieldValue *dflt)
{
return add(&VrmlNodeType::addExposedField, type, name, dflt);
}
int
add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *),
const char *typeString, const char *name,
const VrmlFieldValue *dflt)
{
int type = fieldType(typeString);
if (type == 0) {
cerr << "Error: invalid field type: " << type << "\n";
}
// Need to add support for Script nodes:
// if (inScript) ... ???
if (currentProtoStack.empty()) {
cerr << "Error: declaration outside of prototype\n";
return 0;
}
VrmlNodeType *t = currentProtoStack.top();
(t->*func)(name, type, dflt);
return type;
}
int
fieldType(const char *type)
{
if (strcmp(type, "SFBool") == 0) return SFBOOL;
if (strcmp(type, "SFColor") == 0) return SFCOLOR;
if (strcmp(type, "SFFloat") == 0) return SFFLOAT;
if (strcmp(type, "SFImage") == 0) return SFIMAGE;
if (strcmp(type, "SFInt32") == 0) return SFINT32;
if (strcmp(type, "SFNode") == 0) return SFNODE;
if (strcmp(type, "SFRotation") == 0) return SFROTATION;
if (strcmp(type, "SFString") == 0) return SFSTRING;
if (strcmp(type, "SFTime") == 0) return SFTIME;
if (strcmp(type, "SFVec2f") == 0) return SFVEC2F;
if (strcmp(type, "SFVec3f") == 0) return SFVEC3F;
if (strcmp(type, "MFColor") == 0) return MFCOLOR;
if (strcmp(type, "MFFloat") == 0) return MFFLOAT;
if (strcmp(type, "MFInt32") == 0) return MFINT32;
if (strcmp(type, "MFNode") == 0) return MFNODE;
if (strcmp(type, "MFRotation") == 0) return MFROTATION;
if (strcmp(type, "MFString") == 0) return MFSTRING;
if (strcmp(type, "MFVec2f") == 0) return MFVEC2F;
if (strcmp(type, "MFVec3f") == 0) return MFVEC3F;
cerr << "Illegal field type: " << type << "\n";
return 0;
}
void
enterNode(const char *nodeType)
{
const VrmlNodeType *t = VrmlNodeType::find(nodeType);
if (t == NULL) {
char tmp[1000];
sprintf(tmp, "Unknown node type '%s'", nodeType);
vrmlyyerror(tmp);
}
FieldRec *fr = new FieldRec;
fr->nodeType = t;
fr->fieldName = NULL;
fr->typeRec = NULL;
currentField.push(fr);
VrmlNode *node = new VrmlNode(t);
currentNode.push(node);
}
VrmlNode *
exitNode()
{
FieldRec *fr = currentField.top();
nassertr(fr != NULL, NULL);
currentField.pop();
VrmlNode *node = currentNode.top();
nassertr(node != NULL, NULL);
currentNode.pop();
// cerr << "Just defined node:\n" << *node << "\n\n";
delete fr;
return node;
}
void
inScript()
{
FieldRec *fr = currentField.top();
if (fr->nodeType == NULL ||
strcmp(fr->nodeType->getName(), "Script") != 0) {
vrmlyyerror("interface declaration outside of Script or prototype");
}
}
void
enterField(const char *fieldName)
{
FieldRec *fr = currentField.top();
nassertv(fr != NULL);
fr->fieldName = fieldName;
fr->typeRec = NULL;
if (fr->nodeType != NULL) {
// enterField is called when parsing eventIn and eventOut IS
// declarations, in which case we don't need to do anything special--
// the IS IDENTIFIER will be returned from the lexer normally.
if (fr->nodeType->hasEventIn(fieldName) ||
fr->nodeType->hasEventOut(fieldName))
return;
const VrmlNodeType::NameTypeRec *typeRec =
fr->nodeType->hasField(fieldName);
if (typeRec != NULL) {
fr->typeRec = typeRec;
// Let the lexer know what field type to expect:
expect(typeRec->type);
}
else {
cerr << "Error: Nodes of type " << fr->nodeType->getName() <<
" do not have fields/eventIn/eventOut named " <<
fieldName << "\n";
// expect(ANY_FIELD);
}
}
// else expect(ANY_FIELD);
}
void
storeField(const VrmlFieldValue &value) {
FieldRec *fr = currentField.top();
nassertv(fr != NULL);
VrmlNode *node = currentNode.top();
nassertv(node != NULL);
if (fr->typeRec != NULL) {
node->_fields.push_back(VrmlNode::Field(fr->typeRec, value));
}
}
void
exitField()
{
FieldRec *fr = currentField.top();
nassertv(fr != NULL);
fr->fieldName = NULL;
fr->typeRec = NULL;
}
void
expect(int type)
{
expectToken = type;
}

View File

@ -0,0 +1,28 @@
// Filename: vrmlParserDefs.h
// Created by: drose (30Sep04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VRMLPARSERDEFS_H
#define VRMLPARSERDEFS_H
#include "pandatoolbase.h"
void vrml_init_parser(istream &in, const string &filename);
void vrml_cleanup_parser();
int vrmlyyparse();
#endif

View File

@ -0,0 +1,20 @@
#begin ss_lib_target
#define TARGET vrmlegg
#define LOCAL_LIBS converter pvrml pandatoolbase
#define OTHER_LIBS \
egg:c event:c pandaegg:m \
mathutil:c linmath:c putil:c express:c panda:m \
interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#define SOURCES \
indexedFaceSet.cxx indexedFaceSet.h \
vrmlAppearance.cxx vrmlAppearance.h \
vrmlToEggConverter.cxx vrmlToEggConverter.h
#define INSTALL_HEADERS \
indexedFaceSet.h \
vrmlAppearance.h \
vrmlToEggConverter.h
#end ss_lib_target

View File

@ -0,0 +1,582 @@
// Filename: indexedFaceSet.cxx
// 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 "indexedFaceSet.h"
#include "vrmlAppearance.h"
#include "vrmlNodeType.h"
#include "vrmlNode.h"
#include "notify.h"
#include "eggGroup.h"
#include "eggVertex.h"
#include "eggVertexPool.h"
#include "eggPolygon.h"
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
IndexedFaceSet::
IndexedFaceSet(const VrmlNode *geometry, const VRMLAppearance &appearance) :
_geometry(geometry), _appearance(appearance)
{
get_coord_values();
get_polys();
get_colors();
_has_normals = get_normals();
if (!_per_vertex_normals.empty()) {
assign_per_vertex_normals();
}
get_uvs();
if (!_per_vertex_uvs.empty()) {
assign_per_vertex_uvs();
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::convert_to_egg
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
convert_to_egg(EggGroup *group, const LMatrix4d &net_transform) {
EggVertexPool *vpool = new EggVertexPool(group->get_name());
group->add_child(vpool);
make_polys(vpool, group, net_transform);
if (!_has_normals && _appearance._has_material) {
compute_normals(group);
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_coord_values
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
get_coord_values() {
const VrmlNode *coord = _geometry->get_value("coord")._sfnode._p;
if (coord != NULL) {
const MFArray *point = coord->get_value("point")._mf;
MFArray::const_iterator ci;
for (ci = point->begin(); ci != point->end(); ++ci) {
const double *p = (*ci)._sfvec;
_coord_values.push_back(Vertexd(p[0], p[1], p[2]));
}
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_polys
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
get_polys() {
const MFArray *coordIndex = _geometry->get_value("coordIndex")._mf;
VrmlPolygon poly;
MFArray::const_iterator ci;
for (ci = coordIndex->begin(); ci != coordIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0) {
_polys.push_back(poly);
poly._verts.clear();
} else {
const Vertexd &p = _coord_values[(*ci)._sfint32];
VrmlVertex vert;
vert._index = (*ci)._sfint32;
vert._pos = p;
poly._verts.push_back(vert);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_vrml_colors
// Access: Private
// Description: Builds up a vector of Colorf pointers corresponding
// to the VRML color node.
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
get_vrml_colors(const VrmlNode *color_node, double transparency,
pvector<Colorf> &color_list) {
const MFArray *color = color_node->get_value("color")._mf;
MFArray::const_iterator ci;
for (ci = color->begin(); ci != color->end(); ++ci) {
const double *p = (*ci)._sfvec;
Colorf color(p[0], p[1], p[2], 1.0 - transparency);
color_list.push_back(color);
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_vrml_normals
// Access: Private
// Description: Builds up a vector of double array pointers corresponding
// to the VRML normal node.
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
get_vrml_normals(const VrmlNode *normal_node,
pvector<Normald> &normal_list) {
const MFArray *point = normal_node->get_value("vector")._mf;
MFArray::const_iterator ci;
for (ci = point->begin(); ci != point->end(); ++ci) {
const double *p = (*ci)._sfvec;
Normald normal(p[0], p[1], p[2]);
normal_list.push_back(normal);
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_vrml_uvs
// Access: Private
// Description: Builds up a vector of double array pointers corresponding
// to the VRML texCoord node.
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
get_vrml_uvs(const VrmlNode *texCoord_node,
pvector<TexCoordd> &uv_list) {
const MFArray *point = texCoord_node->get_value("point")._mf;
MFArray::const_iterator ci;
for (ci = point->begin(); ci != point->end(); ++ci) {
const double *p = (*ci)._sfvec;
TexCoordd uv(p[0], p[1]);
uv_list.push_back(uv);
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_colors
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool IndexedFaceSet::
get_colors() {
const VrmlNode *color = _geometry->get_value("color")._sfnode._p;
if (color != NULL) {
// Vertex or face colors.
pvector<Colorf> color_list;
get_vrml_colors(color, _appearance._transparency, color_list);
bool colorPerVertex = _geometry->get_value("colorPerVertex")._sfbool;
MFArray *colorIndex = _geometry->get_value("colorIndex")._mf;
if (colorPerVertex) {
MFArray::const_iterator ci;
size_t pi = 0;
size_t pv = 0;
for (ci = colorIndex->begin(); ci != colorIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0) {
// End of poly.
if (pv != _polys[pi]._verts.size()) {
cerr << "Color indices don't match up!\n";
return false;
}
pi++;
pv = 0;
} else {
if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) {
cerr << "Color indices don't match up!\n";
return false;
}
_polys[pi]._verts[pv]._attrib.set_color(color_list[(*ci)._sfint32]);
pv++;
}
}
if (pi != _polys.size()) {
cerr << "Not enough color indices!\n";
return false;
}
} else {
if (!colorIndex->empty()) {
MFArray::const_iterator ci;
size_t pi = 0;
if (colorIndex->size() != _polys.size()) {
cerr << "Wrong number of color indices!\n";
return false;
}
for (ci = colorIndex->begin(); ci != colorIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0 || (*ci)._sfint32 >= (int)color_list.size()) {
cerr << "Invalid color index!\n";
return false;
}
_polys[pi]._attrib.set_color(color_list[(*ci)._sfint32]);
pi++;
}
} else {
if (color_list.size() != _polys.size()) {
cerr << "Wrong number of colors!\n";
return false;
}
for (size_t pi = 0; pi < color_list.size(); pi++) {
_polys[pi]._attrib.set_color(color_list[pi]);
}
}
}
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_normals
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool IndexedFaceSet::
get_normals() {
const VrmlNode *normal = _geometry->get_value("normal")._sfnode._p;
if (normal != NULL) {
// Vertex or face normals.
pvector<Normald> normal_list;
get_vrml_normals(normal, normal_list);
bool normalPerVertex = _geometry->get_value("normalPerVertex")._sfbool;
MFArray *normalIndex = _geometry->get_value("normalIndex")._mf;
MFArray::const_iterator ci;
if (normalPerVertex &&
normal_list.size() == _polys.size() &&
normalIndex->empty()) {
// Here's an interesting formZ bug. We end up with a VRML file
// that claims to have normals per vertex, yet there is no
// normal index list, and there are exactly enough normals in
// the list to indicate one normal per face. Silly formZ.
normalPerVertex = false;
}
if (normalPerVertex) {
if (normalIndex->empty()) {
// If we have *no* normal index array, but we do have
// per-vertex normals, assume the VRML writer meant to imply a
// one-to-one mapping. This works around a broken formZ VRML
// file writer.
for (size_t i = 0; i < normal_list.size(); i++) {
VrmlFieldValue fv;
fv._sfint32 = i;
(*normalIndex).push_back(fv);
}
}
// It's possible that this .wrl file indexes normals directly
// into the vertex array, instead of into the polygon list.
// Check for this possibility. This can only happen if the
// number of normal indices exactly matches the number of
// vertices, and none of the indices is -1.
bool linear_list = (normalIndex->size() == _coord_values.size());
for (ci = normalIndex->begin();
ci != normalIndex->end() && linear_list;
++ci) {
linear_list = ((*ci)._sfint32 >= 0);
}
if (linear_list) {
// Ok, we do have such a list. This .wrl file seems to store
// its texture coordinates one per vertex, instead of one per
// polygon vertex.
_per_vertex_normals.reserve(_coord_values.size());
for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) {
size_t vi = (*ci)._sfint32;
nassertr(vi >= 0, false);
if (vi >= normal_list.size()) {
cerr << "Invalid normal index: " << vi << "\n";
return false;
}
_per_vertex_normals.push_back(normal_list[vi]);
}
nassertr(_per_vertex_normals.size() == _coord_values.size(), false);
} else {
// This is a "correct" .wrl file that stores its texture
// coordinates one per polygon vertex. This allows a shared
// vertex to contain two different normal values in differing
// polygons (meaning it's not actually shared).
MFArray::const_iterator ci;
size_t pi = 0;
size_t pv = 0;
for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0) {
// End of poly.
if (pv != _polys[pi]._verts.size()) {
cerr << "Normal indices don't match up!\n";
return false;
}
pi++;
pv = 0;
} else {
if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) {
cerr << "Normal indices don't match up!\n";
return false;
}
const Normald &d = normal_list[(*ci)._sfint32];
_polys[pi]._verts[pv]._attrib.set_normal(d);
pv++;
}
}
if (pi != _polys.size()) {
cerr << "Not enough normal indices!\n";
return false;
}
}
} else {
if (!normalIndex->empty()) {
size_t pi = 0;
if (normalIndex->size() != _polys.size()) {
cerr << "Wrong number of normal indices!\n";
return false;
}
for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0 || (*ci)._sfint32 >= (int)normal_list.size()) {
cerr << "Invalid normal index!\n";
return false;
}
const Normald &d = normal_list[(*ci)._sfint32];
_polys[pi]._attrib.set_normal(d);
pi++;
}
} else {
if (normal_list.size() != _polys.size()) {
cerr << "Wrong number of normals!\n";
return false;
}
for (size_t pi = 0; pi < normal_list.size(); pi++) {
const Normald &d = normal_list[pi];
_polys[pi]._attrib.set_normal(d);
}
}
}
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::assign_per_vertex_normals
// Access: Private
// Description: Once the array of _per_vertex_normals has been filled
// (by a broken .wrl file that indexes the normal's
// directly into the vertex array instead of per polygon
// vertex), go back through the polygons and assign the
// normals by index number.
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
assign_per_vertex_normals() {
for (size_t pi = 0; pi < _polys.size(); pi++) {
for (size_t pv = 0; pv < _polys[pi]._verts.size(); pv++) {
VrmlVertex &vv = _polys[pi]._verts[pv];
if (vv._index >= 0 && vv._index < (int)_per_vertex_normals.size()) {
const Normald &d = _per_vertex_normals[vv._index];
vv._attrib.set_normal(d);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::get_uvs
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool IndexedFaceSet::
get_uvs() {
const VrmlNode *texCoord = _geometry->get_value("texCoord")._sfnode._p;
if (texCoord != NULL) {
// Vertex or face texCoords.
pvector<TexCoordd> uv_list;
get_vrml_uvs(texCoord, uv_list);
MFArray *texCoordIndex = _geometry->get_value("texCoordIndex")._mf;
MFArray::const_iterator ci;
if (texCoordIndex->empty()) {
// If we have *no* texture coordinate index array, but we do
// have texture coordinates, assume the VRML writer meant to
// imply a one-to-one mapping. This works around a broken formZ
// VRML file writer.
for (size_t i = 0; i < uv_list.size(); i++) {
VrmlFieldValue fv;
fv._sfint32 = i;
(*texCoordIndex).push_back(fv);
}
}
// It's possible that this .wrl file indexes texture coordinates
// directly into the vertex array, instead of into the polygon
// list. Check for this possibility. This can only happen if the
// number of texture coordinate indices exactly matches the number
// of vertices, and none of the indices is -1.
bool linear_list = (texCoordIndex->size() == _coord_values.size());
for (ci = texCoordIndex->begin();
ci != texCoordIndex->end() && linear_list;
++ci) {
linear_list = ((*ci)._sfint32 >= 0);
}
if (linear_list) {
// Ok, we do have such a list. This .wrl file seems to store
// its texture coordinates one per vertex, instead of one per
// polygon vertex.
_per_vertex_uvs.reserve(_coord_values.size());
for (ci = texCoordIndex->begin(); ci != texCoordIndex->end(); ++ci) {
size_t vi = (*ci)._sfint32;
nassertr(vi >= 0, false);
if (vi >= uv_list.size()) {
cerr << "Invalid texCoord index: " << vi << "\n";
return false;
}
_per_vertex_uvs.push_back(uv_list[vi]);
}
nassertr(_per_vertex_uvs.size() == _coord_values.size(), false);
} else {
// This is a "correct" .wrl file that stores its texture
// coordinates one per polygon vertex. This allows a shared
// vertex to contain two different texture coordinate values in
// differing polygons (meaning it's not actually shared).
size_t pi = 0;
size_t pv = 0;
for (ci = texCoordIndex->begin(); ci != texCoordIndex->end(); ++ci) {
if ((*ci)._sfint32 < 0) {
// End of poly.
if (pv != _polys[pi]._verts.size()) {
cerr << "texCoord indices don't match up!\n";
return false;
}
pi++;
pv = 0;
} else {
if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) {
cerr << "texCoord indices don't match up!\n";
return false;
}
_polys[pi]._verts[pv]._attrib.set_uv(uv_list[(*ci)._sfint32]);
pv++;
}
}
if (pi != _polys.size()) {
cerr << "Not enough texCoord indices!\n";
return false;
}
}
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::assign_per_vertex_uvs
// Access: Private
// Description: Once the array of _per_vertex_uvs has been filled (by
// a broken .wrl file that indexes the uv's directly
// into the vertex array instead of per polygon vertex),
// go back through the polygons and assign the UV's by
// index number.
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
assign_per_vertex_uvs() {
for (size_t pi = 0; pi < _polys.size(); pi++) {
for (size_t pv = 0; pv < _polys[pi]._verts.size(); pv++) {
VrmlVertex &vv = _polys[pi]._verts[pv];
if (vv._index >= 0 && vv._index < (int)_per_vertex_uvs.size()) {
const TexCoordd &d = _per_vertex_uvs[vv._index];
vv._attrib.set_uv(d);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::make_polys
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
make_polys(EggVertexPool *vpool, EggGroup *group,
const LMatrix4d &net_transform) {
bool ccw = _geometry->get_value("ccw")._sfbool;
bool solid = _geometry->get_value("solid")._sfbool;
for (size_t pi = 0; pi < _polys.size(); pi++) {
EggPolygon *poly = new EggPolygon;
group->add_child(poly);
poly->copy_attributes(_polys[pi]._attrib);
if (!poly->has_color() && _appearance._has_material) {
poly->set_color(_appearance._color);
}
if (_appearance._tex != NULL) {
poly->set_texture(_appearance._tex);
}
if (!solid) {
poly->set_bface_flag(true);
}
if (ccw) {
// The vertices are counterclockwise, same as Egg.
for (int pv = 0; pv < (int)_polys[pi]._verts.size(); pv++) {
EggVertex vert(_polys[pi]._verts[pv]._attrib);
Vertexd pos =
_polys[pi]._verts[pv]._pos * net_transform;
vert.set_pos(pos);
poly->add_vertex(vpool->create_unique_vertex(vert));
}
} else {
// The vertices are clockwise, so add 'em in reverse order.
for (int pv = (int)_polys[pi]._verts.size() - 1; pv >= 0; pv--) {
EggVertex vert(_polys[pi]._verts[pv]._attrib);
Vertexd pos =
_polys[pi]._verts[pv]._pos * net_transform;
vert.set_pos(pos);
poly->add_vertex(vpool->create_unique_vertex(vert));
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: IndexedFaceSet::compute_normals
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void IndexedFaceSet::
compute_normals(EggGroup *group) {
const VrmlNode *normal = _geometry->get_value("normal")._sfnode._p;
if (normal == NULL) {
// Compute normals.
double creaseAngle = _geometry->get_value("creaseAngle")._sffloat;
if (creaseAngle == 0.0) {
group->recompute_polygon_normals();
} else {
group->recompute_vertex_normals(rad_2_deg(creaseAngle));
}
}
}

View File

@ -0,0 +1,84 @@
// Filename: indexedFaceSet.h
// 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.
////////////////////////////////////////////////////////////////////
#ifndef INDEXEDFACESET_H
#define INDEXEDFACESET_H
#include "pandatoolbase.h"
#include "pvector.h"
#include "pset.h"
#include "eggPolygon.h"
#include "eggVertex.h"
#include "eggAttributes.h"
class VrmlNode;
class EggData;
class EggGroup;
class EggVertexPool;
class VRMLAppearance;
class LMatrix4d;
////////////////////////////////////////////////////////////////////
// Class : IndexedFaceSet
// Description : Decodes the vertices and faces in a VRML indexed face
// set, and creates the corresponding egg geometry.
////////////////////////////////////////////////////////////////////
class IndexedFaceSet {
public:
IndexedFaceSet(const VrmlNode *geometry, const VRMLAppearance &appearance);
void convert_to_egg(EggGroup *group, const LMatrix4d &net_transform);
private:
void get_coord_values();
void get_polys();
void get_vrml_colors(const VrmlNode *color_node, double transparency,
pvector<Colorf> &color_list);
void get_vrml_normals(const VrmlNode *normal_node,
pvector<Normald> &normal_list);
void get_vrml_uvs(const VrmlNode *texCoord_node,
pvector<TexCoordd> &uv_list);
bool get_colors();
bool get_normals();
void assign_per_vertex_normals();
bool get_uvs();
void assign_per_vertex_uvs();
void make_polys(EggVertexPool *vpool, EggGroup *group,
const LMatrix4d &net_transform);
void compute_normals(EggGroup *group);
class VrmlVertex {
public:
int _index;
Vertexd _pos;
EggVertex _attrib;
};
class VrmlPolygon {
public:
EggPolygon _attrib;
pvector<VrmlVertex> _verts;
};
pvector<Vertexd> _coord_values;
pvector<VrmlPolygon> _polys;
pvector<TexCoordd> _per_vertex_uvs;
pvector<Normald> _per_vertex_normals;
bool _has_normals;
const VrmlNode *_geometry;
const VRMLAppearance &_appearance;
};
#endif

View File

@ -0,0 +1,46 @@
// Filename: vrmlAppearance.cxx
// 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 "vrmlAppearance.h"
#include "vrmlNode.h"
VRMLAppearance::
VRMLAppearance(const VrmlNode *appearance) {
_has_material = false;
_transparency = 0.0;
_color.set(1.0f, 1.0f, 1.0f, 1.0f);
if (appearance != NULL) {
const VrmlNode *material = appearance->get_value("material")._sfnode._p;
if (material != NULL) {
_has_material = true;
const double *c = material->get_value("diffuseColor")._sfvec;
_transparency = material->get_value("transparency")._sffloat;
_color.set(c[0], c[1], c[2], 1.0 - _transparency);
}
const VrmlNode *texture = appearance->get_value("texture")._sfnode._p;
if (texture != NULL) {
if (strcmp(texture->_type->getName(), "ImageTexture") == 0) {
MFArray *url = texture->get_value("url")._mf;
if (!url->empty()) {
const char *filename = (*url->begin())._sfstring;
_tex = new EggTexture("tref", filename);
}
}
}
}
}

View File

@ -0,0 +1,34 @@
// Filename: vrmlAppearance.h
// 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.
////////////////////////////////////////////////////////////////////
#ifndef VRMLAPPEARANCE_H
#define VRMLAPPEARANCE_H
#include "pandatoolbase.h"
#include "eggTexture.h"
#include "pt_EggTexture.h"
class VrmlNode;
class VRMLAppearance {
public:
VRMLAppearance(const VrmlNode *vrmlAppearance);
bool _has_material;
Colorf _color;
double _transparency;
PT_EggTexture _tex;
};
#endif

View File

@ -0,0 +1,411 @@
// Filename: vrmlToEggConverter.cxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "vrmlToEggConverter.h"
#include "vrmlAppearance.h"
#include "indexedFaceSet.h"
#include "vrmlNodeType.h"
#include "parse_vrml.h"
#include "vrmlParser.h"
#include "eggGroupNode.h"
#include "eggGroup.h"
#include "eggData.h"
#include "deg_2_rad.h"
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VRMLToEggConverter::
VRMLToEggConverter() {
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VRMLToEggConverter::
VRMLToEggConverter(const VRMLToEggConverter &copy) :
SomethingToEggConverter(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VRMLToEggConverter::
~VRMLToEggConverter() {
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::make_copy
// Access: Public, Virtual
// Description: Allocates and returns a new copy of the converter.
////////////////////////////////////////////////////////////////////
SomethingToEggConverter *VRMLToEggConverter::
make_copy() {
return new VRMLToEggConverter(*this);
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::get_name
// Access: Public, Virtual
// Description: Returns the English name of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string VRMLToEggConverter::
get_name() const {
return "VRML";
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::get_extension
// Access: Public, Virtual
// Description: Returns the common extension of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string VRMLToEggConverter::
get_extension() const {
return "wrl";
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::convert_file
// Access: Public, Virtual
// Description: Handles the reading of the input file and converting
// it to egg. Returns true if successful, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool VRMLToEggConverter::
convert_file(const Filename &filename) {
VrmlScene *scene = parse_vrml(filename);
if (scene == (VrmlScene *)NULL) {
return false;
}
if (_egg_data->get_coordinate_system() == CS_default) {
_egg_data->set_coordinate_system(CS_yup_right);
}
// 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.
VrmlScene::const_iterator csi;
for (csi = scene->begin(); csi != scene->end(); ++csi) {
vrml_node((*csi)._node, &get_egg_data(), LMatrix4d::ident_mat());
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::get_all_defs
// Access: Private
// 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 VRMLToEggConverter::
get_all_defs(SFNodeRef &vrml, VRMLToEggConverter::Nodes &nodes) {
Nodes::iterator ni;
switch (vrml._type) {
case SFNodeRef::T_def:
// If this is a node definition, add it to the map.
nassertv(vrml._name != NULL);
nassertv(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.
nassertv(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: VRMLToEggConverter::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 VRMLToEggConverter::
vrml_node(const SFNodeRef &vrml, EggGroupNode *egg,
const LMatrix4d &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,
&VRMLToEggConverter::vrml_group);
} else if (strcmp(node->_type->getName(), "Transform") == 0) {
vrml_grouping_node(vrml, egg, net_transform,
&VRMLToEggConverter::vrml_transform);
} else if (strcmp(node->_type->getName(), "Shape") == 0) {
vrml_grouping_node(vrml, egg, net_transform,
&VRMLToEggConverter::vrml_shape);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::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 VRMLToEggConverter::
vrml_grouping_node(const SFNodeRef &vrml, EggGroupNode *egg,
const LMatrix4d &net_transform,
void (VRMLToEggConverter::*process_func)
(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform)) {
const VrmlNode *node = vrml._p;
nassertv(node != NULL);
string name;
if (vrml._name != NULL) {
name = vrml._name;
}
/*
The following code fragment was used in the old DWD-style egg
library. Currently, the Panda egg library doesn't support
instance references, so we deal with VRML instances by copying.
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;
}
*/
PT(EggGroup) group = new EggGroup(name);
egg->add_child(group);
LMatrix4d next_transform = net_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->set_group_type(EggGroup::GT_instance);
next_transform = LMatrix4d::ident_mat();
// And define the instance for future references.
// _instances[node] = group;
}
(this->*process_func)(node, group, next_transform);
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEggConverter::vrml_group
// Access: Public
// Description: Creates an Egg group corresponding to the VRML group.
////////////////////////////////////////////////////////////////////
void VRMLToEggConverter::
vrml_group(const VrmlNode *node, EggGroup *group,
const LMatrix4d &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: VRMLToEggConverter::vrml_transform
// Access: Public
// Description: Creates an Egg group with a transform corresponding
// to the VRML group.
////////////////////////////////////////////////////////////////////
void VRMLToEggConverter::
vrml_transform(const VrmlNode *node, EggGroup *group,
const LMatrix4d &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;
LMatrix4d local_transform = LMatrix4d::ident_mat();
bool 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 *=
LMatrix4d::translate_mat(-center[0], -center[1], -center[2]);
if (o[3] != 0.0) {
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(-o[3]), LVector3d(o[0], o[1], o[2]));
local_transform *=
LMatrix4d::scale_mat(scale[0], scale[1], scale[2]);
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(o[3]), LVector3d(o[0], o[1], o[2]));
} else {
local_transform *=
LMatrix4d::scale_mat(scale[0], scale[1], scale[2]);
}
local_transform *=
LMatrix4d::translate_mat(center[0], center[1], center[2]);
} else {
if (o[3] != 0.0) {
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(-o[3]), LVector3d(o[0], o[1], o[2]));
local_transform *=
LMatrix4d::scale_mat(scale[0], scale[1], scale[2]);
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(o[3]), LVector3d(o[0], o[1], o[2]));
} else {
local_transform *=
LMatrix4d::scale_mat(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 *=
LMatrix4d::translate_mat(-center[0], -center[1], -center[2]);
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(rotation[3]),
LVector3d(rotation[0], rotation[1], rotation[2]));
local_transform *=
LMatrix4d::translate_mat(center[0], center[1], center[2]);
} else {
local_transform *=
LMatrix4d::rotate_mat(rad_2_deg(rotation[3]),
LVector3d(rotation[0], rotation[1], rotation[2]));
}
}
if (translation[0] != 0.0 ||
translation[1] != 0.0 ||
translation[2] != 0.0) {
any_transform = true;
local_transform *=
LMatrix4d::translate_mat(translation[0], translation[1], translation[2]);
}
if (any_transform) {
group->set_transform(local_transform);
}
LMatrix4d 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: VRMLToEggConverter::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 VRMLToEggConverter::
vrml_shape(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform) {
const VrmlNode *geometry = node->get_value("geometry")._sfnode._p;
double transparency = 0.0;
if (geometry != NULL) {
VRMLAppearance appearance(node->get_value("appearance")._sfnode._p);
if (strcmp(geometry->_type->getName(), "IndexedFaceSet") == 0) {
IndexedFaceSet ifs(geometry, appearance);
ifs.convert_to_egg(group, net_transform);
} else {
cerr << "Ignoring " << geometry->_type->getName() << "\n";
}
}
}

View File

@ -0,0 +1,73 @@
// Filename: vrmlToEggConverter.h
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VRMLTOEGGCONVERTER_H
#define VRMLTOEGGCONVERTER_H
#include "pandatoolbase.h"
#include "somethingToEggConverter.h"
#include "pmap.h"
class VrmlNode;
struct SFNodeRef;
class EggGroupNode;
class EggGroup;
class LMatrix4d;
////////////////////////////////////////////////////////////////////
// Class : VRMLToEggConverter
// Description : This class supervises the construction of an EggData
// structure from a VRML file.
////////////////////////////////////////////////////////////////////
class VRMLToEggConverter : public SomethingToEggConverter {
public:
VRMLToEggConverter();
VRMLToEggConverter(const VRMLToEggConverter &copy);
~VRMLToEggConverter();
virtual SomethingToEggConverter *make_copy();
virtual string get_name() const;
virtual string get_extension() const;
virtual bool convert_file(const Filename &filename);
private:
typedef pmap<string, VrmlNode *> Nodes;
void get_all_defs(SFNodeRef &vrml, Nodes &nodes);
void vrml_node(const SFNodeRef &vrml, EggGroupNode *egg,
const LMatrix4d &net_transform);
void vrml_grouping_node(const SFNodeRef &vrml, EggGroupNode *egg,
const LMatrix4d &net_transform,
void (VRMLToEggConverter::*process_func)
(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform));
void vrml_group(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform);
void vrml_transform(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform);
void vrml_shape(const VrmlNode *node, EggGroup *group,
const LMatrix4d &net_transform);
};
#endif

View File

@ -0,0 +1,28 @@
#begin bin_target
#define TARGET vrml2egg
#define LOCAL_LIBS pvrml vrmlegg eggbase progbase
#define OTHER_LIBS \
egg:c pandaegg:m \
linmath:c pnmimagetypes:c pnmimage:c putil:c mathutil:c event:c panda:m \
express:c pandaexpress:m \
dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
#define SOURCES \
vrmlToEgg.cxx vrmlToEgg.h
#end bin_target
#begin bin_target
#define TARGET vrml-trans
#define LOCAL_LIBS \
progbase pvrml
#define OTHER_LIBS \
linmath:c panda:m \
express:c pandaexpress:m \
dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
#define SOURCES \
vrmlTrans.cxx vrmlTrans.h
#end bin_target

View File

@ -0,0 +1,80 @@
// Filename: vrmlToEgg.cxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "vrmlToEgg.h"
#include "vrmlToEggConverter.h"
////////////////////////////////////////////////////////////////////
// Function: VRMLToEgg::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VRMLToEgg::
VRMLToEgg() :
SomethingToEgg("VRML", ".wrl")
{
add_units_options();
add_normals_options();
add_transform_options();
set_program_description
("This program converts VRML 2.0 model files to egg. Animated files, "
"and VRML 1.0 files, are not supported.");
redescribe_option
("cs",
"Specify the coordinate system of the input " + _format_name +
" file. Normally, this is y-up.");
_coordinate_system = CS_yup_right;
}
////////////////////////////////////////////////////////////////////
// Function: VRMLToEgg::run
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void VRMLToEgg::
run() {
nout << "Reading " << _input_filename << "\n";
_data.set_coordinate_system(_coordinate_system);
VRMLToEggConverter converter;
converter.set_egg_data(&_data, false);
converter._allow_errors = _allow_errors;
apply_parameters(converter);
if (!converter.convert_file(_input_filename)) {
nout << "Errors in conversion.\n";
exit(1);
}
write_egg_file();
nout << "\n";
}
int main(int argc, char *argv[]) {
VRMLToEgg prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}

View File

@ -0,0 +1,41 @@
// Filename: vrmlToEgg.h
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VRMLTOEGG_H
#define VRMLTOEGG_H
#include "pandatoolbase.h"
#include "somethingToEgg.h"
#include "vrmlToEggConverter.h"
////////////////////////////////////////////////////////////////////
// Class : VRMLToEgg
// Description : A program to read a VRML file and generate an egg
// file.
////////////////////////////////////////////////////////////////////
class VRMLToEgg : public SomethingToEgg {
public:
VRMLToEgg();
void run();
};
#endif

View File

@ -0,0 +1,104 @@
// Filename: vrmlTrans.cxx
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "vrmlTrans.h"
#include "parse_vrml.h"
////////////////////////////////////////////////////////////////////
// Function: VRMLTrans::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VRMLTrans::
VRMLTrans() :
WithOutputFile(true, true, false)
{
// Indicate the extension name we expect the user to supply for
// output files.
_preferred_extension = ".wrl";
set_program_description
("This program reads a VRML 2.0 file (.wrl) and writes an "
"essentially equivalent .wrl file. It is primarily useful for "
"debugging the VRML parser that is part of the Pandatool library.");
clear_runlines();
add_runline("[opts] input.wrl > output.wrl");
add_runline("[opts] input.wrl output.wrl");
add_runline("[opts] -o output.wrl input.wrl");
add_option
("o", "filename", 0,
"Specify the filename to which the resulting .wrl file will be written. "
"If this option is omitted, the last parameter name is taken to be the "
"name of the output file.",
&VRMLTrans::dispatch_filename, &_got_output_filename, &_output_filename);
}
////////////////////////////////////////////////////////////////////
// Function: VRMLTrans::run
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void VRMLTrans::
run() {
nout << "Reading " << _input_filename << "\n";
VrmlScene *scene = parse_vrml(_input_filename);
if (scene == (VrmlScene *)NULL) {
nout << "Unable to read.\n";
exit(1);
}
get_output() << *scene << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: VRMLTrans::handle_args
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool VRMLTrans::
handle_args(ProgramBase::Args &args) {
if (!check_last_arg(args, 1)) {
return false;
}
if (args.empty()) {
nout << "You must specify the .wrl file to read on the command line.\n";
return false;
} else if (args.size() != 1) {
nout << "You must specify only one .wrl file to read on the command line.\n";
return false;
}
_input_filename = args[0];
return true;
}
int main(int argc, char *argv[]) {
VRMLTrans prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}

View File

@ -0,0 +1,46 @@
// Filename: vrmlTrans.h
// Created by: drose (01Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef VRMLTRANS_H
#define VRMLTRANS_H
#include "pandatoolbase.h"
#include "programBase.h"
#include "withOutputFile.h"
////////////////////////////////////////////////////////////////////
// Class : VRMLTrans
// Description : A program to read a VRML file and output an
// essentially similar VRML file. This is mainly useful
// to test the VRML parser used in Panda.
////////////////////////////////////////////////////////////////////
class VRMLTrans : public ProgramBase, public WithOutputFile {
public:
VRMLTrans();
void run();
protected:
virtual bool handle_args(Args &args);
Filename _input_filename;
};
#endif