mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-06 20:03:16 -04:00
428 lines
15 KiB
C++
428 lines
15 KiB
C++
// Filename: eggBase.cxx
|
|
// Created by: drose (14Feb00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "eggBase.h"
|
|
|
|
#include "eggGroupNode.h"
|
|
#include "eggTexture.h"
|
|
#include "eggFilenameNode.h"
|
|
#include "eggComment.h"
|
|
#include "dcast.h"
|
|
#include "string_utils.h"
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggBase::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
EggBase::
|
|
EggBase() {
|
|
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'.",
|
|
&EggBase::dispatch_coordinate_system,
|
|
&_got_coordinate_system, &_coordinate_system);
|
|
|
|
_normals_mode = NM_preserve;
|
|
_normals_threshold = 0.0;
|
|
|
|
_got_transform = false;
|
|
_transform = LMatrix4d::ident_mat();
|
|
|
|
_got_coordinate_system = false;
|
|
_coordinate_system = CS_yup_right;
|
|
|
|
_noabs = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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.
|
|
////////////////////////////////////////////////////////////////////
|
|
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);
|
|
|
|
add_option
|
|
("tbn", "name", 48,
|
|
"Compute tangent and binormal for the named texture coordinate "
|
|
"set(s). The name may include wildcard characters such as * and ?. "
|
|
"The normal must already exist or have been computed via one of the "
|
|
"above options. The tangent and binormal are used to implement "
|
|
"bump mapping and related texture-based lighting effects. This option "
|
|
"may be repeated as necessary to name multiple texture coordinate sets.",
|
|
&EggBase::dispatch_vector_string, NULL, &_tbn_names);
|
|
|
|
add_option
|
|
("tbnall", "", 48,
|
|
"Compute tangent and binormal for all texture coordinate "
|
|
"sets. This is equivalent to -tbn \"*\".",
|
|
&EggBase::dispatch_none, &_got_tbnall);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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.
|
|
////////////////////////////////////////////////////////////////////
|
|
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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggBase::convert_paths
|
|
// Access: Public, Static
|
|
// Description: Recursively walks the egg hierarchy. Any filenames
|
|
// encountered are replaced according to the indicated
|
|
// PathReplace.
|
|
////////////////////////////////////////////////////////////////////
|
|
void EggBase::
|
|
convert_paths(EggNode *node, PathReplace *path_replace,
|
|
const DSearchPath &additional_path) {
|
|
if (node->is_of_type(EggTexture::get_class_type())) {
|
|
EggTexture *egg_tex = DCAST(EggTexture, node);
|
|
Filename fullpath, outpath;
|
|
path_replace->full_convert_path(egg_tex->get_filename(), additional_path,
|
|
fullpath, outpath);
|
|
egg_tex->set_filename(outpath);
|
|
egg_tex->set_fullpath(fullpath);
|
|
|
|
if (egg_tex->has_alpha_filename()) {
|
|
Filename alpha_fullpath, alpha_outpath;
|
|
path_replace->full_convert_path(egg_tex->get_alpha_filename(), additional_path,
|
|
alpha_fullpath, alpha_outpath);
|
|
egg_tex->set_alpha_filename(alpha_outpath);
|
|
egg_tex->set_alpha_fullpath(alpha_fullpath);
|
|
}
|
|
|
|
} else if (node->is_of_type(EggFilenameNode::get_class_type())) {
|
|
EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node);
|
|
|
|
Filename fullpath, outpath;
|
|
path_replace->full_convert_path(egg_fnode->get_filename(), additional_path,
|
|
fullpath, outpath);
|
|
egg_fnode->set_filename(outpath);
|
|
egg_fnode->set_fullpath(fullpath);
|
|
|
|
} else if (node->is_of_type(EggGroupNode::get_class_type())) {
|
|
EggGroupNode *egg_group = DCAST(EggGroupNode, node);
|
|
EggGroupNode::const_iterator ci;
|
|
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
|
convert_paths(*ci, path_replace, additional_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggBase::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.
|
|
//
|
|
// Normally this function is called automatically when
|
|
// appropriate by EggWriter, and it's not necessary to
|
|
// call it explicitly.
|
|
////////////////////////////////////////////////////////////////////
|
|
void EggBase::
|
|
append_command_comment(EggData *data) {
|
|
append_command_comment(data, get_exec_command());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggBase::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 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;
|
|
}
|