split out EggBase and EggSingleBase

This commit is contained in:
David Rose 2003-07-21 18:34:46 +00:00
parent fb01954822
commit 4bf8b08394
16 changed files with 549 additions and 444 deletions

View File

@ -21,13 +21,13 @@
#include "charPlacement.h"
#include "pkFontFile.h"
#include <string_utils.h>
#include <eggGroup.h>
#include <eggTexture.h>
#include <eggVertexPool.h>
#include <eggPolygon.h>
#include <eggPoint.h>
#include <pointerTo.h>
#include "string_utils.h"
#include "eggGroup.h"
#include "eggTexture.h"
#include "eggVertexPool.h"
#include "eggPolygon.h"
#include "eggPoint.h"
#include "pointerTo.h"
#include <math.h>
@ -220,7 +220,7 @@ handle_args(ProgramBase::Args &args) {
////////////////////////////////////////////////////////////////////
bool EggMakeFont::
dispatch_dimensions(ProgramBase *self, const string &opt, const string &arg, void *) {
EggBase *base = (EggBase *)self;
EggSingleBase *base = (EggSingleBase *)self;
EggMakeFont *me = (EggMakeFont *)base->as_writer();
return me->ns_dispatch_dimensions(opt, arg);
}

View File

@ -19,13 +19,13 @@
#ifndef EGGMAKEFONT_H
#define EGGMAKEFONT_H
#include <pandatoolbase.h>
#include "pandatoolbase.h"
#include "charLayout.h"
#include <eggWriter.h>
#include <luse.h>
#include <pnmImage.h>
#include "eggWriter.h"
#include "luse.h"
#include "pnmImage.h"
class CharPlacement;
class CharBitmap;

View File

@ -37,6 +37,8 @@ EggOptchar::
EggOptchar() {
add_path_replace_options();
add_path_store_options();
add_normals_options();
add_transform_options();
set_program_description
("egg-optchar performs basic optimizations of a character model "

View File

@ -9,18 +9,20 @@
#define SOURCES \
eggBase.h eggConverter.h eggFilter.h eggMultiBase.h \
eggMultiFilter.h eggReader.h eggToSomething.h eggWriter.h \
eggMultiFilter.h eggReader.h eggSingleBase.h \
eggToSomething.h eggWriter.h \
somethingToEgg.h
#define INCLUDED_SOURCES \
eggBase.cxx eggConverter.cxx eggFilter.cxx eggMultiBase.cxx \
eggMultiFilter.cxx eggReader.cxx eggToSomething.cxx \
eggMultiFilter.cxx eggReader.cxx eggSingleBase.cxx \
eggToSomething.cxx \
eggWriter.cxx somethingToEgg.cxx
#define INSTALL_HEADERS \
eggBase.h eggConverter.h eggFilter.h \
eggMultiBase.h eggMultiFilter.h \
eggReader.h eggToSomething.h eggWriter.h somethingToEgg.h
eggReader.h eggSingleBase.h eggToSomething.h eggWriter.h somethingToEgg.h
#end ss_lib_target

View File

@ -23,6 +23,7 @@
#include "eggFilenameNode.h"
#include "eggComment.h"
#include "dcast.h"
#include "string_utils.h"
////////////////////////////////////////////////////////////////////
// Function: EggBase::Constructor
@ -39,40 +40,86 @@ EggBase() {
&_got_coordinate_system, &_coordinate_system);
_coordinate_system = CS_yup_right;
_normals_mode = NM_preserve;
_normals_threshold = 0.0;
_got_transform = false;
_transform = LMatrix4d::ident_mat();
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::as_reader
// Access: Public, Virtual
// Description: Returns this object as an EggReader pointer, if it is
// in fact an EggReader, or NULL if it is not.
//
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggBase, we need functions like this to downcast
// to the appropriate pointer.
// Function: EggBase::add_normals_options
// Access: Public
// Description: Adds -no, -np, etc. as valid options for this
// program. If the user specifies one of the options on
// the command line, the normals will be adjusted when
// the egg file is written out.
////////////////////////////////////////////////////////////////////
EggReader *EggBase::
as_reader() {
return (EggReader *)NULL;
void EggBase::
add_normals_options() {
static NormalsMode strip = NM_strip;
static NormalsMode polygon = NM_polygon;
static NormalsMode vertex = NM_vertex;
static NormalsMode preserve = NM_preserve;
add_option
("no", "", 48,
"Strip all normals.",
&EggBase::dispatch_normals, NULL, &strip);
add_option
("np", "", 48,
"Strip existing normals and redefine polygon normals.",
&EggBase::dispatch_normals, NULL, &polygon);
add_option
("nv", "threshold", 48,
"Strip existing normals and redefine vertex normals. Consider an edge "
"between adjacent polygons to be smooth if the angle between them "
"is less than threshold degrees.",
&EggBase::dispatch_normals, NULL, &vertex);
add_option
("nn", "", 48,
"Preserve normals exactly as they are. This is the default.",
&EggBase::dispatch_normals, NULL, &preserve);
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::as_writer
// Access: Public, Virtual
// Description: Returns this object as an EggWriter pointer, if it is
// in fact an EggWriter, or NULL if it is not.
//
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggBase, we need functions like this to downcast
// to the appropriate pointer.
// Function: EggBase::add_transform_options
// Access: Public
// Description: Adds -TS, -TT, etc. as valid options for this
// program. If the user specifies one of the options on
// the command line, the data will be transformed when
// the egg file is written out.
////////////////////////////////////////////////////////////////////
EggWriter *EggBase::
as_writer() {
return (EggWriter *)NULL;
void EggBase::
add_transform_options() {
add_option
("TS", "sx[,sy,sz]", 49,
"Scale the model uniformly by the given factor (if only one number "
"is given) or in each axis by sx, sy, sz (if three numbers are given).",
&EggBase::dispatch_scale, &_got_transform, &_transform);
add_option
("TR", "x,y,z", 49,
"Rotate the model x degrees about the x axis, then y degrees about the "
"y axis, and then z degrees about the z axis.",
&EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);
add_option
("TA", "angle,x,y,z", 49,
"Rotate the model angle degrees counterclockwise about the given "
"axis.",
&EggBase::dispatch_rotate_axis, &_got_transform, &_transform);
add_option
("TT", "x,y,z", 49,
"Translate the model by the indicated amount.\n\n"
"All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
"applied in the order they are encountered on the command line.",
&EggBase::dispatch_translate, &_got_transform, &_transform);
}
////////////////////////////////////////////////////////////////////
@ -116,21 +163,6 @@ convert_paths(EggNode *node, PathReplace *path_replace,
}
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::post_command_line
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool EggBase::
post_command_line() {
if (_got_coordinate_system) {
_data.set_coordinate_system(_coordinate_system);
}
return ProgramBase::post_command_line();
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::append_command_comment
// Access: Protected
@ -162,3 +194,212 @@ void EggBase::
append_command_comment(EggData &data, const string &comment) {
data.insert(data.begin(), new EggComment("", comment));
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::dispatch_normals
// Access: Protected, Static
// Description: Accepts one of -no, -np, etc. and sets _normals_mode
// as indicated. The void * argument is a pointer to a
// NormalsMode variable that indicates which switch was
// passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
EggBase *base = (EggBase *)self;
return base->ns_dispatch_normals(opt, arg, mode);
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::ns_dispatch_normals
// Access: Protected
// Description: Accepts one of -no, -np, etc. and sets _normals_mode
// as indicated. The void * argument is a pointer to a
// NormalsMode variable that indicates which switch was
// passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
_normals_mode = *(NormalsMode *)mode;
if (_normals_mode == NM_vertex) {
if (!string_to_double(arg, _normals_threshold)) {
nout << "Invalid numeric parameter for -" << opt << ": "
<< arg << "\n";
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::dispatch_scale
// Access: Protected, Static
// Description: Handles -TS, which specifies a scale transform. Var
// is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_scale(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
double sx, sy, sz;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], sx) &&
string_to_double(words[1], sy) &&
string_to_double(words[2], sz);
} else if (words.size() == 1) {
okflag =
string_to_double(words[0], sx);
sy = sz = sx;
}
if (!okflag) {
nout << "-" << opt
<< " requires one or three numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::dispatch_rotate_xyz
// Access: Protected, Static
// Description: Handles -TR, which specifies a rotate transform about
// the three cardinal axes. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
EggBase *base = (EggBase *)self;
return base->ns_dispatch_rotate_xyz(opt, arg, var);
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::ns_dispatch_rotate_xyz
// Access: Protected
// Description: Handles -TR, which specifies a rotate transform about
// the three cardinal axes. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
LVecBase3d xyz;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], xyz[0]) &&
string_to_double(words[1], xyz[1]) &&
string_to_double(words[2], xyz[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires three numbers separated by commas.\n";
return false;
}
LMatrix4d mat =
LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
*transform = (*transform) * mat;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::dispatch_rotate_axis
// Access: Protected, Static
// Description: Handles -TA, which specifies a rotate transform about
// an arbitrary axis. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
EggBase *base = (EggBase *)self;
return base->ns_dispatch_rotate_axis(opt, arg, var);
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::ns_dispatch_rotate_axis
// Access: Protected
// Description: Handles -TA, which specifies a rotate transform about
// an arbitrary axis. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
double angle;
LVecBase3d axis;
bool okflag = false;
if (words.size() == 4) {
okflag =
string_to_double(words[0], angle) &&
string_to_double(words[1], axis[0]) &&
string_to_double(words[2], axis[1]) &&
string_to_double(words[3], axis[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires four numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggBase::dispatch_translate
// Access: Protected, Static
// Description: Handles -TT, which specifies a translate transform.
// Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_translate(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
LVector3d trans;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], trans[0]) &&
string_to_double(words[1], trans[1]) &&
string_to_double(words[2], trans[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires three numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::translate_mat(trans);
return true;
}

View File

@ -22,20 +22,13 @@
#include "pandatoolbase.h"
#include "programBase.h"
#include "coordinateSystem.h"
#include "eggData.h"
class EggReader;
class EggWriter;
class EggNode;
class PathReplace;
////////////////////////////////////////////////////////////////////
// Class : EggBase
// Description : This specialization of ProgramBase is intended for
// programs that read and/or write a single egg file.
// (See EggMultiBase for programs that operate on
// multiple egg files at once.)
// Description : This is a base class for both EggSingleBase and
// EggMultiBase. Don't inherit directly from this; use
// one of those two classes instead.
//
// This is just a base class; see EggReader, EggWriter,
// or EggFilter according to your particular I/O needs.
@ -44,21 +37,41 @@ class EggBase : public ProgramBase {
public:
EggBase();
virtual EggReader *as_reader();
virtual EggWriter *as_writer();
void add_normals_options();
void add_transform_options();
static void convert_paths(EggNode *node, PathReplace *path_replace,
const DSearchPath &additional_path);
protected:
virtual bool post_command_line();
void append_command_comment(EggData &_data);
static void append_command_comment(EggData &_data, const string &comment);
static bool dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode);
bool ns_dispatch_normals(const string &opt, const string &arg, void *mode);
static bool dispatch_scale(const string &opt, const string &arg, void *var);
static bool dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var);
bool ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var);
static bool dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var);
bool ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var);
static bool dispatch_translate(const string &opt, const string &arg, void *var);
protected:
enum NormalsMode {
NM_strip,
NM_polygon,
NM_vertex,
NM_preserve
};
NormalsMode _normals_mode;
double _normals_threshold;
bool _got_transform;
LMatrix4d _transform;
bool _got_coordinate_system;
CoordinateSystem _coordinate_system;
EggData _data;
};
#endif

View File

@ -30,54 +30,78 @@
////////////////////////////////////////////////////////////////////
EggMultiBase::
EggMultiBase() {
add_option
("cs", "coordinate-system", 80,
"Specify the coordinate system to operate in. This may be one of "
"'y-up', 'z-up', 'y-up-left', or 'z-up-left'.",
&EggMultiBase::dispatch_coordinate_system,
&_got_coordinate_system, &_coordinate_system);
add_option
("f", "", 80,
"Force complete loading: load up the egg file along with all of its "
"external references.",
&EggMultiBase::dispatch_none, &_force_complete);
_coordinate_system = CS_yup_right;
}
////////////////////////////////////////////////////////////////////
// Function: EggMultiBase::append_command_comment
// Access: Protected
// Description: Inserts a comment into the beginning of the indicated
// egg file corresponding to the command line that
// invoked this program.
// Function: EggMultiBase::post_process_egg_files
// Access: Public
// Description: Performs any processing of the egg file(s) that is
// appropriate before writing them out. This includes any
// normal adjustments the user requested via -np, etc.
//
// Normally this function is called automatically when
// appropriate by EggWriter, and it's not necessary to
// call it explicitly.
// Normally, you should not need to call this function
// directly; write_egg_files() calls it for you. You
// should call this only if you do not use
// write_egg_files() to write out the resulting egg
// files.
////////////////////////////////////////////////////////////////////
void EggMultiBase::
append_command_comment(EggData &data) {
append_command_comment(data, get_exec_command());
post_process_egg_files() {
if (_eggs.empty()) {
return;
}
Eggs::iterator ei;
if (_got_transform) {
nout << "Applying transform matrix:\n";
_transform.write(nout, 2);
LVecBase3d scale, hpr, translate;
if (decompose_matrix(_transform, scale, hpr, translate,
_eggs[0]->get_coordinate_system())) {
nout << "(scale " << scale << ", hpr " << hpr << ", translate "
<< translate << ")\n";
}
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
(*ei)->transform(_transform);
}
}
switch (_normals_mode) {
case NM_strip:
nout << "Stripping normals.\n";
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
(*ei)->strip_normals();
(*ei)->remove_unused_vertices();
}
break;
case NM_polygon:
nout << "Recomputing polygon normals.\n";
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
(*ei)->recompute_polygon_normals();
(*ei)->remove_unused_vertices();
}
break;
case NM_vertex:
nout << "Recomputing vertex normals.\n";
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
(*ei)->recompute_vertex_normals(_normals_threshold);
(*ei)->remove_unused_vertices();
}
break;
case NM_preserve:
// Do nothing.
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMultiBase::append_command_comment
// Access: Protected, Static
// Description: Inserts a comment into the beginning of the indicated
// egg file corresponding to the command line that
// invoked this program.
//
// Normally this function is called automatically when
// appropriate by EggWriter, and it's not necessary to
// call it explicitly.
////////////////////////////////////////////////////////////////////
void EggMultiBase::
append_command_comment(EggData &data, const string &comment) {
data.insert(data.begin(), new EggComment("", comment));
}
////////////////////////////////////////////////////////////////////
// Function: EggMultiBase::read_egg

View File

@ -19,12 +19,12 @@
#ifndef EGGMULTIBASE_H
#define EGGMULTIBASE_H
#include <pandatoolbase.h>
#include "pandatoolbase.h"
#include <programBase.h>
#include <coordinateSystem.h>
#include <eggData.h>
#include <pointerTo.h>
#include "eggBase.h"
#include "coordinateSystem.h"
#include "eggData.h"
#include "pointerTo.h"
class Filename;
@ -37,21 +37,17 @@ class Filename;
// how to read a bunch of egg files in and write them
// out again.
////////////////////////////////////////////////////////////////////
class EggMultiBase : public ProgramBase {
class EggMultiBase : public EggBase {
public:
EggMultiBase();
protected:
void append_command_comment(EggData &_data);
static void append_command_comment(EggData &_data, const string &comment);
void post_process_egg_files();
protected:
virtual PT(EggData) read_egg(const Filename &filename);
protected:
bool _got_coordinate_system;
CoordinateSystem _coordinate_system;
typedef pvector<PT(EggData)> Eggs;
typedef pvector< PT(EggData) > Eggs;
Eggs _eggs;
bool _force_complete;

View File

@ -189,6 +189,7 @@ get_output_filename(const Filename &source_filename) const {
void EggMultiFilter::
write_eggs() {
nassertv(!_read_only);
post_process_egg_files();
Eggs::iterator ei;
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
EggData *data = (*ei);

View File

@ -136,7 +136,7 @@ add_delod_options(double default_delod) {
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggBase, we need functions like this to downcast
// from EggSingleBase, we need functions like this to downcast
// to the appropriate pointer.
////////////////////////////////////////////////////////////////////
EggReader *EggReader::
@ -211,7 +211,7 @@ handle_args(ProgramBase::Args &args) {
////////////////////////////////////////////////////////////////////
bool EggReader::
post_command_line() {
return EggBase::post_command_line();
return EggSingleBase::post_command_line();
}
////////////////////////////////////////////////////////////////////

View File

@ -21,7 +21,7 @@
#include "pandatoolbase.h"
#include "eggBase.h"
#include "eggSingleBase.h"
#include "filename.h"
class PNMFileType;
@ -31,7 +31,7 @@ class PNMFileType;
// Description : This is the base class for a program that reads egg
// files, but doesn't write an egg file.
////////////////////////////////////////////////////////////////////
class EggReader : virtual public EggBase {
class EggReader : virtual public EggSingleBase {
public:
EggReader();

View File

@ -0,0 +1,84 @@
// Filename: eggSingleBase.cxx
// Created by: drose (21Jul03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "eggSingleBase.h"
#include "eggGroupNode.h"
#include "eggTexture.h"
#include "eggFilenameNode.h"
#include "eggComment.h"
#include "dcast.h"
#include "string_utils.h"
////////////////////////////////////////////////////////////////////
// Function: EggSingleBase::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggSingleBase::
EggSingleBase() {
}
////////////////////////////////////////////////////////////////////
// Function: EggSingleBase::as_reader
// Access: Public, Virtual
// Description: Returns this object as an EggReader pointer, if it is
// in fact an EggReader, or NULL if it is not.
//
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggSingleBase, we need functions like this to downcast
// to the appropriate pointer.
////////////////////////////////////////////////////////////////////
EggReader *EggSingleBase::
as_reader() {
return (EggReader *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggSingleBase::as_writer
// Access: Public, Virtual
// Description: Returns this object as an EggWriter pointer, if it is
// in fact an EggWriter, or NULL if it is not.
//
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggSingleBase, we need functions like this to downcast
// to the appropriate pointer.
////////////////////////////////////////////////////////////////////
EggWriter *EggSingleBase::
as_writer() {
return (EggWriter *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggSingleBase::post_command_line
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool EggSingleBase::
post_command_line() {
if (_got_coordinate_system) {
_data.set_coordinate_system(_coordinate_system);
}
return EggBase::post_command_line();
}

View File

@ -0,0 +1,59 @@
// Filename: eggSingleBase.h
// Created by: drose (21Jul03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef EGGSINGLEBASE_H
#define EGGSINGLEBASE_H
#include "pandatoolbase.h"
#include "eggBase.h"
#include "coordinateSystem.h"
#include "eggData.h"
class EggReader;
class EggWriter;
class EggNode;
class PathReplace;
////////////////////////////////////////////////////////////////////
// Class : EggSingleBase
// Description : This specialization of EggBase is intended for
// programs that read and/or write a single egg file.
// (See EggMultiBase for programs that operate on
// multiple egg files at once.)
//
// This is just a base class; see EggReader, EggWriter,
// or EggFilter according to your particular I/O needs.
////////////////////////////////////////////////////////////////////
class EggSingleBase : public EggBase {
public:
EggSingleBase();
virtual EggReader *as_reader();
virtual EggWriter *as_writer();
protected:
virtual bool post_command_line();
protected:
EggData _data;
};
#endif

View File

@ -92,89 +92,9 @@ EggWriter(bool allow_last_param, bool allow_stdout) :
"Specify the coordinate system of the resulting egg file. This may be "
"one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is "
"y-up.");
_normals_mode = NM_preserve;
_normals_threshold = 0.0;
_got_transform = false;
_transform = LMatrix4d::ident_mat();
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::add_normals_options
// Access: Public
// Description: Adds -no, -np, etc. as valid options for this
// program. If the user specifies one of the options on
// the command line, the normals will be adjusted when
// the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggWriter::
add_normals_options() {
static NormalsMode strip = NM_strip;
static NormalsMode polygon = NM_polygon;
static NormalsMode vertex = NM_vertex;
static NormalsMode preserve = NM_preserve;
add_option
("no", "", 48,
"Strip all normals.",
&EggWriter::dispatch_normals, NULL, &strip);
add_option
("np", "", 48,
"Strip existing normals and redefine polygon normals.",
&EggWriter::dispatch_normals, NULL, &polygon);
add_option
("nv", "threshold", 48,
"Strip existing normals and redefine vertex normals. Consider an edge "
"between adjacent polygons to be smooth if the angle between them "
"is less than threshold degrees.",
&EggWriter::dispatch_normals, NULL, &vertex);
add_option
("nn", "", 48,
"Preserve normals exactly as they are. This is the default.",
&EggWriter::dispatch_normals, NULL, &preserve);
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::add_transform_options
// Access: Public
// Description: Adds -TS, -TT, etc. as valid options for this
// program. If the user specifies one of the options on
// the command line, the data will be transformed when
// the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggWriter::
add_transform_options() {
add_option
("TS", "sx[,sy,sz]", 49,
"Scale the model uniformly by the given factor (if only one number "
"is given) or in each axis by sx, sy, sz (if three numbers are given).",
&EggWriter::dispatch_scale, &_got_transform, &_transform);
add_option
("TR", "x,y,z", 49,
"Rotate the model x degrees about the x axis, then y degrees about the "
"y axis, and then z degrees about the z axis.",
&EggWriter::dispatch_rotate_xyz, &_got_transform, &_transform);
add_option
("TA", "angle,x,y,z", 49,
"Rotate the model angle degrees counterclockwise about the given "
"axis.",
&EggWriter::dispatch_rotate_axis, &_got_transform, &_transform);
add_option
("TT", "x,y,z", 49,
"Translate the model by the indicated amount.\n\n"
"All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
"applied in the order they are encountered on the command line.",
&EggWriter::dispatch_translate, &_got_transform, &_transform);
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::as_writer
// Access: Public, Virtual
@ -184,7 +104,7 @@ add_transform_options() {
// This is intended to work around the C++ limitation
// that prevents downcasts past virtual inheritance.
// Since both EggReader and EggWriter inherit virtually
// from EggBase, we need functions like this to downcast
// from EggSingleBase, we need functions like this to downcast
// to the appropriate pointer.
////////////////////////////////////////////////////////////////////
EggWriter *EggWriter::
@ -304,217 +224,5 @@ post_command_line() {
append_command_comment(_data);
return EggBase::post_command_line();
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::dispatch_normals
// Access: Protected, Static
// Description: Accepts one of -no, -np, etc. and sets _normals_mode
// as indicated. The void * argument is a pointer to a
// NormalsMode variable that indicates which switch was
// passed.
////////////////////////////////////////////////////////////////////
bool EggWriter::
dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
EggBase *base = (EggBase *)self;
EggWriter *me = base->as_writer();
return me->ns_dispatch_normals(opt, arg, mode);
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::ns_dispatch_normals
// Access: Protected
// Description: Accepts one of -no, -np, etc. and sets _normals_mode
// as indicated. The void * argument is a pointer to a
// NormalsMode variable that indicates which switch was
// passed.
////////////////////////////////////////////////////////////////////
bool EggWriter::
ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
_normals_mode = *(NormalsMode *)mode;
if (_normals_mode == NM_vertex) {
if (!string_to_double(arg, _normals_threshold)) {
nout << "Invalid numeric parameter for -" << opt << ": "
<< arg << "\n";
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::dispatch_scale
// Access: Protected, Static
// Description: Handles -TS, which specifies a scale transform. Var
// is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
dispatch_scale(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
double sx, sy, sz;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], sx) &&
string_to_double(words[1], sy) &&
string_to_double(words[2], sz);
} else if (words.size() == 1) {
okflag =
string_to_double(words[0], sx);
sy = sz = sx;
}
if (!okflag) {
nout << "-" << opt
<< " requires one or three numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::dispatch_rotate_xyz
// Access: Protected, Static
// Description: Handles -TR, which specifies a rotate transform about
// the three cardinal axes. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
EggBase *base = (EggBase *)self;
EggWriter *me = base->as_writer();
return me->ns_dispatch_rotate_xyz(opt, arg, var);
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::ns_dispatch_rotate_xyz
// Access: Protected
// Description: Handles -TR, which specifies a rotate transform about
// the three cardinal axes. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
LVecBase3d xyz;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], xyz[0]) &&
string_to_double(words[1], xyz[1]) &&
string_to_double(words[2], xyz[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires three numbers separated by commas.\n";
return false;
}
LMatrix4d mat =
LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
*transform = (*transform) * mat;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::dispatch_rotate_axis
// Access: Protected, Static
// Description: Handles -TA, which specifies a rotate transform about
// an arbitrary axis. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
EggBase *base = (EggBase *)self;
EggWriter *me = base->as_writer();
return me->ns_dispatch_rotate_axis(opt, arg, var);
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::ns_dispatch_rotate_axis
// Access: Protected
// Description: Handles -TA, which specifies a rotate transform about
// an arbitrary axis. Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
double angle;
LVecBase3d axis;
bool okflag = false;
if (words.size() == 4) {
okflag =
string_to_double(words[0], angle) &&
string_to_double(words[1], axis[0]) &&
string_to_double(words[2], axis[1]) &&
string_to_double(words[3], axis[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires four numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggWriter::dispatch_translate
// Access: Protected, Static
// Description: Handles -TT, which specifies a translate transform.
// Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggWriter::
dispatch_translate(const string &opt, const string &arg, void *var) {
LMatrix4d *transform = (LMatrix4d *)var;
vector_string words;
tokenize(arg, words, ",");
LVector3d trans;
bool okflag = false;
if (words.size() == 3) {
okflag =
string_to_double(words[0], trans[0]) &&
string_to_double(words[1], trans[1]) &&
string_to_double(words[2], trans[2]);
}
if (!okflag) {
nout << "-" << opt
<< " requires three numbers separated by commas.\n";
return false;
}
*transform = (*transform) * LMatrix4d::translate_mat(trans);
return true;
return EggSingleBase::post_command_line();
}

View File

@ -20,7 +20,7 @@
#define EGGWRITER_H
#include "pandatoolbase.h"
#include "eggBase.h"
#include "eggSingleBase.h"
#include "withOutputFile.h"
#include "filename.h"
@ -31,13 +31,10 @@
// Description : This is the base class for a program that generates
// an egg file output, but doesn't read any for input.
////////////////////////////////////////////////////////////////////
class EggWriter : virtual public EggBase, public WithOutputFile {
class EggWriter : virtual public EggSingleBase, public WithOutputFile {
public:
EggWriter(bool allow_last_param = false, bool allow_stdout = true);
void add_normals_options();
void add_transform_options();
virtual EggWriter *as_writer();
virtual void post_process_egg_file();
@ -47,29 +44,6 @@ protected:
virtual bool handle_args(Args &args);
virtual bool post_command_line();
static bool dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode);
bool ns_dispatch_normals(const string &opt, const string &arg, void *mode);
static bool dispatch_scale(const string &opt, const string &arg, void *var);
static bool dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var);
bool ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var);
static bool dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var);
bool ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var);
static bool dispatch_translate(const string &opt, const string &arg, void *var);
protected:
enum NormalsMode {
NM_strip,
NM_polygon,
NM_vertex,
NM_preserve
};
NormalsMode _normals_mode;
double _normals_threshold;
bool _got_transform;
LMatrix4d _transform;
private:
ofstream _output_stream;
ostream *_output_ptr;

View File

@ -6,6 +6,7 @@
#include "eggMultiFilter.cxx"
#include "eggReader.cxx"
#include "eggWriter.cxx"
#include "eggSingleBase.cxx"
#include "eggToSomething.cxx"
#include "somethingToEgg.cxx"