split out maya into mayaegg and mayaprogs

This commit is contained in:
David Rose 2002-04-15 21:56:20 +00:00
parent 351446cb2f
commit 133f94b253
26 changed files with 1169 additions and 446 deletions

View File

@ -1,156 +0,0 @@
// Filename: maya_funcs.cxx
// Created by: drose (16Feb00)
//
////////////////////////////////////////////////////////////////////
//
// 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 "maya_funcs.h"
#include "pre_maya_include.h"
#include <maya/MObject.h>
#include <maya/MAngle.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MStatus.h>
#include <maya/MFnStringData.h>
#include <maya/MFnNumericData.h>
#include "post_maya_include.h"
bool
get_bool_attribute(MObject &node, const string &attribute_name,
bool &value) {
if (!get_maya_attribute(node, attribute_name, value)) {
nout << "Attribute " << attribute_name
<< " does not have an bool value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
return true;
}
bool
get_angle_attribute(MObject &node, const string &attribute_name,
double &value) {
MAngle maya_value;
if (!get_maya_attribute(node, attribute_name, maya_value)) {
nout << "Attribute " << attribute_name
<< " does not have an angle value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
value = maya_value.asDegrees();
return true;
}
bool
get_vec2f_attribute(MObject &node, const string &attribute_name,
LVecBase2f &value) {
MStatus status;
MObject vec2f_object;
if (!get_maya_attribute(node, attribute_name, vec2f_object)) {
nout << "Attribute " << attribute_name
<< " does not have a vec2f object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnNumericData data(vec2f_object, &status);
if (!status) {
nout << "Attribute " << attribute_name << " is of type "
<< vec2f_object.apiTypeStr() << ", not a NumericData.\n";
return false;
}
status = data.getData(value[0], value[1]);
if (!status) {
nout << "Unable to extract 2 floats from " << attribute_name
<< ", of type " << vec2f_object.apiTypeStr() << "\n";
}
return true;
}
bool
get_vec2d_attribute(MObject &node, const string &attribute_name,
LVecBase2d &value) {
MStatus status;
MObject vec2d_object;
if (!get_maya_attribute(node, attribute_name, vec2d_object)) {
nout << "Attribute " << attribute_name
<< " does not have a vec2d object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnNumericData data(vec2d_object, &status);
if (!status) {
nout << "Attribute " << attribute_name << " is of type "
<< vec2d_object.apiTypeStr() << ", not a NumericData.\n";
return false;
}
status = data.getData(value[0], value[1]);
if (!status) {
nout << "Unable to extract 2 doubles from " << attribute_name
<< ", of type " << vec2d_object.apiTypeStr() << "\n";
}
return true;
}
bool
get_string_attribute(MObject &node, const string &attribute_name,
string &value) {
MStatus status;
MObject string_object;
if (!get_maya_attribute(node, attribute_name, string_object)) {
nout << "Attribute " << attribute_name
<< " does not have an string object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnStringData data(string_object, &status);
if (!status) {
nout << "Attribute " << attribute_name << " is of type "
<< string_object.apiTypeStr() << ", not a StringData.\n";
return false;
}
value = data.string().asChar();
return true;
}
void
describe_maya_attribute(MObject &node, const string &attribute_name) {
MStatus status;
MFnDependencyNode node_fn(node, &status);
if (!status) {
nout << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
return;
}
MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
if (!status) {
nout << "Object " << node_fn.name() << " does not support attribute "
<< attribute_name << "\n";
return;
}
nout << "Attribute " << attribute_name << " on object "
<< node_fn.name() << " has type " << attr.apiTypeStr() << "\n";
}

View File

@ -0,0 +1,28 @@
#define DIRECTORY_IF_MAYA yes
#begin ss_lib_target
#define USE_MAYA yes
#define TARGET mayaegg
#define LOCAL_LIBS \
converter pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
linmath:c putil:c panda:m \
express:c pandaexpress:m \
dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
#define UNIX_SYS_LIBS \
m
#define SOURCES \
config_mayaegg.cxx config_mayaegg.h \
mayaApi.cxx mayaApi.h \
mayaParameters.cxx mayaParameters.h \
mayaShader.cxx mayaShader.h \
mayaShaders.cxx mayaShaders.h \
mayaToEggConverter.cxx mayaToEggConverter.h \
maya_funcs.I maya_funcs.cxx maya_funcs.h \
post_maya_include.h pre_maya_include.h
#end ss_lib_target

View File

@ -0,0 +1,46 @@
// Filename: config_mayaegg.cxx
// Created by: drose (15Apr02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "config_mayaegg.h"
#include <dconfig.h>
Configure(config_mayaegg);
NotifyCategoryDef(mayaegg, "");
ConfigureFn(config_mayaegg) {
init_libmayaegg();
}
////////////////////////////////////////////////////////////////////
// Function: init_libmayaegg
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libmayaegg() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
}

View File

@ -1,5 +1,5 @@
// Filename: global_parameters.h
// Created by: drose (16Feb00)
// Filename: config_mayaegg.h
// Created by: drose (15Apr02)
//
////////////////////////////////////////////////////////////////////
//
@ -16,15 +16,14 @@
//
////////////////////////////////////////////////////////////////////
#ifndef GLOBAL_PARAMETERS_H
#define GLOBAL_PARAMETERS_H
#ifndef CONFIG_MAYAEGG_H
#define CONFIG_MAYAEGG_H
#include "pandatoolbase.h"
#include "notifyCategoryProxy.h"
extern int verbose;
extern bool polygon_output;
extern double polygon_tolerance;
extern bool ignore_transforms;
NotifyCategoryDeclNoExport(mayaegg);
extern void init_libmayaegg();
#endif

View File

@ -0,0 +1,207 @@
// Filename: mayaApi.cxx
// Created by: drose (15Apr02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "mayaApi.h"
#include "config_mayaegg.h"
#include "pre_maya_include.h"
#include <maya/MGlobal.h>
#include <maya/MDistance.h>
#include <maya/MFileIO.h>
#include <maya/MLibrary.h>
#include <maya/MStatus.h>
#include "post_maya_include.h"
MayaApi *MayaApi::_global_api = (MayaApi *)NULL;
////////////////////////////////////////////////////////////////////
// Function: MayaApi::Constructor
// Access: Protected
// Description: Don't attempt to create this object directly;
// instead, use the open_api() method.
////////////////////////////////////////////////////////////////////
MayaApi::
MayaApi(const string &program_name) {
MStatus stat = MLibrary::initialize((char *)program_name.c_str());
if (!stat) {
stat.perror("MLibrary::initialize");
_is_valid = false;
} else {
_is_valid = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::Copy Constructor
// Access: Protected
// Description: Don't attempt to copy MayaApi objects. There should
// be only one of these in the world at a time.
////////////////////////////////////////////////////////////////////
MayaApi::
MayaApi(const MayaApi &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::Copy Assignment Operator
// Access: Protected
// Description: Don't attempt to copy MayaApi objects. There should
// be only one of these in the world at a time.
////////////////////////////////////////////////////////////////////
void MayaApi::
operator = (const MayaApi &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaApi::
~MayaApi() {
nassertv(_global_api == this);
if (_is_valid) {
MLibrary::cleanup();
}
_global_api = (MayaApi *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::open_api
// Access: Public, Static
// Description: Opens the Maya API, if it is not already open, and
// returns a pointer representing this connection. When
// you are done using the Maya API, let the pointer
// destruct.
//
// If program_name is supplied, it is passed to Maya as
// the name of the currently-executing program.
// Otherwise, the current program name is extracted from
// the execution environment, if possible.
////////////////////////////////////////////////////////////////////
PT(MayaApi) MayaApi::
open_api(string program_name) {
if (_global_api == (MayaApi *)NULL) {
// We need to create a new MayaApi object.
if (program_name.empty()) {
program_name = ExecutionEnvironment::get_binary_name();
if (program_name.empty()) {
program_name = "Panda";
}
}
_global_api = new MayaApi(program_name);
}
return _global_api;
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::is_valid
// Access: Public
// Description: Returns true if the API has been successfully opened
// and may be used, or false if there is some problem.
////////////////////////////////////////////////////////////////////
bool MayaApi::
is_valid() const {
return _is_valid;
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::read
// Access: Public
// Description: Reads the indicated maya file into the global model
// space. Returns true if successful, false otherwise.
////////////////////////////////////////////////////////////////////
bool MayaApi::
read(const Filename &filename) {
MFileIO::newFile(true);
mayaegg_cat.info() << "Reading " << filename << "\n";
// Load the file into Maya
string os_filename = filename.to_os_specific();
MStatus stat = MFileIO::open(os_filename.c_str());
if (!stat) {
stat.perror(filename.c_str());
return false;
}
mayaegg_cat.info() << "done.\n";
return true;
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::clear
// Access: Public
// Description: Resets the global model space to the empty state, for
// instance in preparation for building a new file.
// Returns true if successful, false otherwise.
////////////////////////////////////////////////////////////////////
bool MayaApi::
clear() {
MStatus stat = MFileIO::newFile(true);
if (!stat) {
stat.perror("clear");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::get_units
// Access: Public
// Description: Returns Maya's internal units in effect.
////////////////////////////////////////////////////////////////////
DistanceUnit MayaApi::
get_units() {
switch (MDistance::internalUnit()) {
case MDistance::kInches:
return DU_inches;
case MDistance::kFeet:
return DU_feet;
case MDistance::kYards:
return DU_yards;
case MDistance::kMiles:
return DU_statute_miles;
case MDistance::kMillimeters:
return DU_millimeters;
case MDistance::kCentimeters:
return DU_centimeters;
case MDistance::kKilometers:
return DU_kilometers;
case MDistance::kMeters:
return DU_meters;
default:
return DU_invalid;
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaApi::get_coordinate_system
// Access: Public
// Description: Returns Maya's internal coordinate system in effect.
////////////////////////////////////////////////////////////////////
CoordinateSystem MayaApi::
get_coordinate_system() {
if (MGlobal::isYAxisUp()) {
return CS_yup_right;
} else {
return CS_zup_right;
}
}

View File

@ -0,0 +1,60 @@
// Filename: mayaApi.h
// Created by: drose (15Apr02)
//
////////////////////////////////////////////////////////////////////
//
// 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 MAYAAPI_H
#define MAYAAPI_H
#include "pandatoolbase.h"
#include "distanceUnit.h"
#include "coordinateSystem.h"
#include "referenceCount.h"
#include "pointerTo.h"
class Filename;
////////////////////////////////////////////////////////////////////
// Class : MayaApi
// Description : This class presents a wrapper around the global
// Maya interface. While the reference count it held,
// it keeps the Maya interface open, and closes the
// interface when the object destructs.
////////////////////////////////////////////////////////////////////
class MayaApi : public ReferenceCount {
protected:
MayaApi(const string &program_name);
MayaApi(const MayaApi &copy);
void operator = (const MayaApi &copy);
public:
~MayaApi();
static PT(MayaApi) open_api(string program_name = "");
bool is_valid() const;
bool read(const Filename &filename);
bool clear();
DistanceUnit get_units();
CoordinateSystem get_coordinate_system();
private:
bool _is_valid;
static MayaApi *_global_api;
};
#endif

View File

@ -1,4 +1,4 @@
// Filename: global_parameters.cxx
// Filename: mayaParameters.cxx
// Created by: drose (16Feb00)
//
////////////////////////////////////////////////////////////////////
@ -16,9 +16,8 @@
//
////////////////////////////////////////////////////////////////////
#include "global_parameters.h"
#include "mayaParameters.h"
int verbose = 0;
bool polygon_output = false;
double polygon_tolerance = 0.01;
bool ignore_transforms = false;
bool MayaParameters::polygon_output = false;
double MayaParameters::polygon_tolerance = 0.01;
bool MayaParameters::ignore_transforms = false;

View File

@ -0,0 +1,38 @@
// Filename: mayaParameters.h
// Created by: drose (16Feb00)
//
////////////////////////////////////////////////////////////////////
//
// 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 MAYAPARAMETERS_H
#define MAYAPARAMETERS_H
#include "pandatoolbase.h"
////////////////////////////////////////////////////////////////////
// Class : MayaParameters
// Description : This class is just used as a scope to hold the global
// parameters for the Maya converter.
////////////////////////////////////////////////////////////////////
class MayaParameters {
public:
static bool polygon_output;
static double polygon_tolerance;
static bool ignore_transforms;
};
#endif

View File

@ -18,8 +18,8 @@
#include "mayaShader.h"
#include "maya_funcs.h"
#include "mayaFile.h"
#include "global_parameters.h"
#include "mayaToEggConverter.h"
#include "config_mayaegg.h"
#include "eggPrimitive.h"
#include "eggTexture.h"
@ -35,8 +35,16 @@
#include <maya/MStatus.h>
#include "post_maya_include.h"
////////////////////////////////////////////////////////////////////
// Function: MayaShader::Constructor
// Access: Public
// Description: Reads the Maya "shading engine" to determine the
// relevant shader properties.
////////////////////////////////////////////////////////////////////
MayaShader::
MayaShader(MObject engine) {
MayaShader(MObject engine, MayaToEggConverter *converter) :
_converter(converter)
{
_has_color = false;
_transparency = 0.0;
@ -59,8 +67,9 @@ MayaShader(MObject engine) {
_name = engine_fn.name().asChar();
if (verbose >= 2) {
nout << "Reading shading engine " << _name << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Reading shading engine " << _name << "\n";
}
bool found_shader = false;
@ -76,14 +85,25 @@ MayaShader(MObject engine) {
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::set_attributes
// Access: Public
// Description: Applies the known shader attributes to the indicated
// egg primitive.
////////////////////////////////////////////////////////////////////
void MayaShader::
set_attributes(EggPrimitive &primitive, MayaFile &file) {
set_attributes(EggPrimitive &primitive, MayaToEggConverter &conv) {
// In Maya, a polygon is either textured or colored. The texture,
// if present, replaces the color.
if (_has_texture) {
EggTextureCollection &textures = file._textures;
EggTexture tex(_name, _texture);
EggTextureCollection &textures = conv._textures;
Filename pathname = _converter->convert_texture_path(_texture);
EggTexture tex(_name, pathname);
tex.set_wrap_u(_wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp);
tex.set_wrap_v(_wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp);
// Let's mipmap all textures by default.
tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
tex.set_magfilter(EggTexture::FT_linear);
@ -103,6 +123,12 @@ set_attributes(EggPrimitive &primitive, MayaFile &file) {
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::compute_texture_matrix
// Access: Public
// Description: Returns a texture matrix corresponding to the texture
// transforms indicated by the shader.
////////////////////////////////////////////////////////////////////
LMatrix3d MayaShader::
compute_texture_matrix() {
LVector2d scale(_repeat_uv[0] / _coverage[0],
@ -118,7 +144,11 @@ compute_texture_matrix() {
LMatrix3d::translate_mat(trans);
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::output
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void MayaShader::
output(ostream &out) const {
out << "Shader " << _name << ":\n";
@ -140,13 +170,20 @@ output(ostream &out) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::read_surface_shader
// Access: Public
// Description: Extracts out the shading information from the Maya
// surface shader.
////////////////////////////////////////////////////////////////////
bool MayaShader::
read_surface_shader(MObject shader) {
MStatus status;
MFnDependencyNode shader_fn(shader);
if (verbose >= 3) {
nout << " Reading surface shader " << shader_fn.name() << "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " Reading surface shader " << shader_fn.name() << "\n";
}
// First, check for a connection to the color attribute. This could
@ -175,13 +212,21 @@ read_surface_shader(MObject shader) {
}
if (!_has_color && !_has_texture) {
if (verbose >= 2) {
nout << " Color definition not found.\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " Color definition not found.\n";
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::read_surface_color
// Access: Public
// Description: Determines the surface color specified by the shader.
// This includes texturing and other advanced shader
// properties.
////////////////////////////////////////////////////////////////////
void MayaShader::
read_surface_color(MObject color) {
if (color.hasFn(MFn::kFileTexture)) {
@ -199,21 +244,22 @@ read_surface_color(MObject color) {
get_vec2f_attribute(color, "repeatUV", _repeat_uv);
get_vec2f_attribute(color, "offset", _offset);
get_angle_attribute(color, "rotateUV", _rotate_uv);
} else {
// This shader wasn't understood.
if (verbose >= 2) {
nout << "**Don't know how to interpret color attribute type "
<< color.apiTypeStr() << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.info()
<< "**Don't know how to interpret color attribute type "
<< color.apiTypeStr() << "\n";
} else {
// If we don't have a heavy verbose count, only report each type
// of unsupportted shader once.
static pset<MFn::Type> bad_types;
if (bad_types.insert(color.apiType()).second) {
if (verbose == 1) {
nout << "\n";
}
nout << "Don't know how to interpret color attribute type "
<< color.apiTypeStr() << "\n";
mayaegg_cat.info()
<< "**Don't know how to interpret color attribute type "
<< color.apiTypeStr() << "\n";
}
}
}

View File

@ -25,14 +25,20 @@
#include "lmatrix.h"
class MObject;
class MayaFile;
class MayaToEggConverter;
class EggPrimitive;
////////////////////////////////////////////////////////////////////
// Class : MayaShader
// Description : Corresponds to a single "shader" in Maya. This
// extracts out all the parameters of a Maya shader that
// are meaningful to egg.
////////////////////////////////////////////////////////////////////
class MayaShader {
public:
MayaShader(MObject engine);
MayaShader(MObject engine, MayaToEggConverter *converter);
void set_attributes(EggPrimitive &primitive, MayaFile &file);
void set_attributes(EggPrimitive &primitive, MayaToEggConverter &conv);
LMatrix3d compute_texture_matrix();
void output(ostream &out) const;
@ -59,9 +65,11 @@ public:
LVector2f _offset;
double _rotate_uv;
protected:
private:
bool read_surface_shader(MObject shader);
void read_surface_color(MObject color);
MayaToEggConverter *_converter;
};
inline ostream &operator << (ostream &out, const MayaShader &shader) {

View File

@ -18,8 +18,8 @@
#include "mayaShaders.h"
#include "mayaShader.h"
#include "global_parameters.h"
#include "maya_funcs.h"
#include "config_mayaegg.h"
#include "pre_maya_include.h"
#include <maya/MStatus.h>
@ -30,6 +30,32 @@
#include <maya/MFn.h>
#include "post_maya_include.h"
////////////////////////////////////////////////////////////////////
// Function: MayaShaders::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaShaders::
MayaShaders(MayaToEggConverter *converter) :
_converter(converter)
{
}
////////////////////////////////////////////////////////////////////
// Function: MayaShaders::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaShaders::
~MayaShaders() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: MayaShaders::find_shader_for_node
// Access: Public
// Description: Extracts the shader assigned to the indicated node.
////////////////////////////////////////////////////////////////////
MayaShader *MayaShaders::
find_shader_for_node(MObject node) {
MStatus status;
@ -39,7 +65,8 @@ find_shader_for_node(MObject node) {
MObject iog_attr = node_fn.attribute("instObjGroups", &status);
if (!status) {
// The node is not renderable. What are you thinking?
nout << node_fn.name() << " : not a renderable object.\n";
mayaegg_cat.error()
<< node_fn.name() << " : not a renderable object.\n";
return (MayaShader *)NULL;
}
@ -52,7 +79,8 @@ find_shader_for_node(MObject node) {
iog_plug.elementByLogicalIndex(0).connectedTo(iog_pa, false, true, &status);
if (!status) {
// No shading group defined for this object.
nout << node_fn.name() << " : no shading group defined.\n";
mayaegg_cat.error()
<< node_fn.name() << " : no shading group defined.\n";
return (MayaShader *)NULL;
}
@ -69,12 +97,19 @@ find_shader_for_node(MObject node) {
}
// Well, we didn't find a ShadingEngine after all. Huh.
if (verbose >= 2) {
nout << node_fn.name() << " : no shading engine found.\n";
}
mayaegg_cat.info()
<< node_fn.name() << " : no shading engine found.\n";
return (MayaShader *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: MayaShaders::find_shader_for_shading_engine
// Access: Public
// Description: Returns the MayaShader object associated with the
// indicated "shading engine". This will create a new
// MayaShader object if this is the first time we have
// encountered the indicated engine.
////////////////////////////////////////////////////////////////////
MayaShader *MayaShaders::
find_shader_for_shading_engine(MObject engine) {
MFnDependencyNode engine_fn(engine);
@ -88,11 +123,25 @@ find_shader_for_shading_engine(MObject engine) {
// All right, this is a newly encountered shading engine. Create a
// new MayaShader object to represent it.
MayaShader *shader = new MayaShader(engine);
MayaShader *shader = new MayaShader(engine, _converter);
// Record this for the future.
_shaders.insert(Shaders::value_type(engine_name, shader));
return shader;
}
////////////////////////////////////////////////////////////////////
// Function: MayaShaders::clear
// Access: Public
// Description: Frees all of the previously-defined MayaShader
// objects associated with this set.
////////////////////////////////////////////////////////////////////
void MayaShaders::
clear() {
Shaders::iterator si;
for (si = _shaders.begin(); si != _shaders.end(); ++si) {
delete (*si).second;
}
_shaders.clear();
}

View File

@ -24,17 +24,28 @@
#include "pmap.h"
class MayaShader;
class MayaToEggConverter;
class MObject;
////////////////////////////////////////////////////////////////////
// Class : MayaShaders
// Description : Collects the set of MayaShaders that have been
// encountered so far.
////////////////////////////////////////////////////////////////////
class MayaShaders {
public:
MayaShaders(MayaToEggConverter *converter);
~MayaShaders();
MayaShader *find_shader_for_node(MObject node);
MayaShader *find_shader_for_shading_engine(MObject engine);
protected:
void clear();
private:
typedef pmap<string, MayaShader *> Shaders;
Shaders _shaders;
MayaToEggConverter *_converter;
};
#endif

View File

@ -1,4 +1,4 @@
// Filename: mayaFile.cxx
// Filename: mayaToEggConverter.cxx
// Created by: drose (10Nov99)
//
////////////////////////////////////////////////////////////////////
@ -16,10 +16,11 @@
//
////////////////////////////////////////////////////////////////////
#include "mayaFile.h"
#include "mayaToEggConverter.h"
#include "mayaShader.h"
#include "global_parameters.h"
#include "mayaParameters.h"
#include "maya_funcs.h"
#include "config_mayaegg.h"
#include "eggData.h"
#include "eggGroup.h"
@ -28,14 +29,12 @@
#include "eggNurbsSurface.h"
#include "eggNurbsCurve.h"
#include "eggPolygon.h"
#include "string_utils.h"
#include "pre_maya_include.h"
#include <maya/MGlobal.h>
#include <maya/MDistance.h>
#include <maya/MArgList.h>
#include <maya/MColor.h>
#include <maya/MDagPath.h>
#include <maya/MFileIO.h>
#include <maya/MFnCamera.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnLight.h>
@ -61,95 +60,110 @@
#include <maya/MTesselationParams.h>
#include "post_maya_include.h"
MayaFile::
MayaFile() {
verbose = 0;
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaToEggConverter::
MayaToEggConverter(const string &program_name) :
_shaders(this)
{
_maya = MayaApi::open_api(program_name);
}
MayaFile::
~MayaFile() {
MLibrary::cleanup();
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaToEggConverter::
MayaToEggConverter(const MayaToEggConverter &copy) :
_shaders(this),
_maya(copy._maya)
{
}
bool MayaFile::
init(const string &program) {
MStatus stat = MLibrary::initialize((char *)program.c_str());
if (!stat) {
stat.perror("MLibrary::initialize");
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
MayaToEggConverter::
~MayaToEggConverter() {
// We have to clear the shaders before we release the Maya API.
_shaders.clear();
_maya.clear();
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::make_copy
// Access: Public, Virtual
// Description: Allocates and returns a new copy of the converter.
////////////////////////////////////////////////////////////////////
SomethingToEggConverter *MayaToEggConverter::
make_copy() {
return new MayaToEggConverter(*this);
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_name
// Access: Public, Virtual
// Description: Returns the English name of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string MayaToEggConverter::
get_name() const {
return "Maya";
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_extension
// Access: Public, Virtual
// Description: Returns the common extension of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string MayaToEggConverter::
get_extension() const {
return "mb";
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::convert_file
// Access: Public, Virtual
// Description: Handles the reading of the input file and converting
// it to egg. Returns true if successful, false
// otherwise.
//
// This is designed to be as generic as possible,
// generally in support of run-time loading.
// Command-line converters may choose to use
// convert_maya() instead, as it provides more control.
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
convert_file(const Filename &filename) {
if (!_maya->is_valid()) {
mayaegg_cat.error()
<< "Maya is not available.\n";
return false;
}
return true;
}
bool MayaFile::
read(const string &filename) {
MFileIO::newFile(true);
nout << "Loading \"" << filename << "\" ... " << flush;
// Load the file into Maya
MStatus stat = MFileIO::open(filename.c_str());
if (!stat) {
stat.perror(filename.c_str());
if (!_maya->read(filename)) {
mayaegg_cat.error()
<< "Unable to read " << filename << "\n";
return false;
}
nout << " done.\n";
return true;
}
void MayaFile::
make_egg(EggData &data) {
traverse(data);
return convert_maya();
}
////////////////////////////////////////////////////////////////////
// Function: MayaFile::get_units
// Access: Public, Static
// Description: Returns Maya's internal units in effect.
// Function: MayaToEggConverter::convert_maya
// Access: Public
// Description: Fills up the egg_data structure according to the
// global maya model data. Returns true if successful,
// false if there is an error.
////////////////////////////////////////////////////////////////////
DistanceUnit MayaFile::
get_units() {
switch (MDistance::internalUnit()) {
case MDistance::kInches:
return DU_inches;
case MDistance::kFeet:
return DU_feet;
case MDistance::kYards:
return DU_yards;
case MDistance::kMiles:
return DU_statute_miles;
case MDistance::kMillimeters:
return DU_millimeters;
case MDistance::kCentimeters:
return DU_centimeters;
case MDistance::kKilometers:
return DU_kilometers;
case MDistance::kMeters:
return DU_meters;
default:
return DU_invalid;
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaFile::get_coordinate_system
// Access: Public, Static
// Description: Returns Maya's internal coordinate system in effect.
////////////////////////////////////////////////////////////////////
CoordinateSystem MayaFile::
get_coordinate_system() {
if (MGlobal::isYAxisUp()) {
return CS_yup_right;
} else {
return CS_zup_right;
}
}
bool MayaFile::
traverse(EggData &data) {
bool MayaToEggConverter::
convert_maya() {
MStatus status;
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
@ -158,32 +172,49 @@ traverse(EggData &data) {
return false;
}
if (verbose >= 1) {
nout << "Traversing scene graph.\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Traversing scene graph.\n";
}
// Scan the entire DAG and output the name and depth of each node
// This while loop walks through the entire Maya hierarchy, one node
// at a time. Maya's MItDag object automatically performs a
// depth-first traversal of its scene graph.
bool all_ok = true;
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
process_node(dag_path, data);
if (!process_node(dag_path, get_egg_data())) {
all_ok = false;
}
}
dag_iterator.next();
}
if (verbose == 1) {
nout << "\nDone.\n";
if (all_ok) {
mayaegg_cat.info()
<< "\nDone, no errors.\n";
} else {
mayaegg_cat.info()
<< "\nDone, errors encountered.\n";
}
return true;
return all_ok;
}
bool MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::process_node
// Access: Private
// Description: Converts the indicated Maya node (given a MDagPath,
// similar in concept to Panda's NodePath) to the
// corresponding Egg structure. Returns true if
// successful, false if an error was encountered.
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
process_node(const MDagPath &dag_path, EggData &data) {
MStatus status;
MFnDagNode dag_node(dag_path, &status);
@ -192,21 +223,22 @@ process_node(const MDagPath &dag_path, EggData &data) {
return false;
}
if (verbose == 1) {
nout << "." << flush;
} else if (verbose >= 2) {
nout << dag_node.name() << ": " << dag_node.typeName() << "\n"
<< " dag_path: " << dag_path.fullPathName() << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< dag_node.name() << ": " << dag_node.typeName() << "\n"
<< " dag_path: " << dag_path.fullPathName() << "\n";
}
if (dag_path.hasFn(MFn::kCamera)) {
if (verbose >= 2) {
nout << "Ignoring camera node " << dag_path.fullPathName() << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring camera node " << dag_path.fullPathName() << "\n";
}
} else if (dag_path.hasFn(MFn::kLight)) {
if (verbose >= 2) {
nout << "Ignoring light node " << dag_path.fullPathName() << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring light node " << dag_path.fullPathName() << "\n";
}
} else if (dag_path.hasFn(MFn::kNurbsSurface)) {
@ -214,17 +246,18 @@ process_node(const MDagPath &dag_path, EggData &data) {
get_egg_group(dag_path.fullPathName().asChar(), data);
if (egg_group == (EggGroup *)NULL) {
nout << "Cannot determine group node.\n";
mayaegg_cat.error()
<< "Cannot determine group node.\n";
return false;
} else {
get_transform(dag_path, egg_group);
MFnNurbsSurface surface(dag_path, &status);
if (!status) {
if (verbose >= 2) {
nout << "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a NURBS surface, but does not.\n";
}
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a NURBS surface, but does not.\n";
} else {
make_nurbs_surface(dag_path, surface, egg_group);
}
@ -242,10 +275,9 @@ process_node(const MDagPath &dag_path, EggData &data) {
MFnNurbsCurve curve(dag_path, &status);
if (!status) {
if (verbose >= 2) {
nout << "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a NURBS curve, but does not.\n";
}
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a NURBS curve, but does not.\n";
} else {
make_nurbs_curve(dag_path, curve, egg_group);
}
@ -256,18 +288,18 @@ process_node(const MDagPath &dag_path, EggData &data) {
get_egg_group(dag_path.fullPathName().asChar(), data);
if (egg_group == (EggGroup *)NULL) {
nout << "Cannot determine group node.\n";
mayaegg_cat.error()
<< "Cannot determine group node.\n";
return false;
} else {
get_transform(dag_path, egg_group);
MFnMesh mesh(dag_path, &status);
if (!status) {
if (verbose >= 2) {
nout << "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a polygon mesh, but does not.\n";
}
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName() << ":\n"
<< " it appears to have a polygon mesh, but does not.\n";
} else {
make_polyset(dag_path, mesh, egg_group);
}
@ -286,17 +318,24 @@ process_node(const MDagPath &dag_path, EggData &data) {
return true;
}
void MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_transform
// Access: Private
// Description: Extracts the transform on the indicated Maya node,
// and applies it to the corresponding Egg node.
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
get_transform(const MDagPath &dag_path, EggGroup *egg_group) {
if (ignore_transforms) {
if (MayaParameters::ignore_transforms) {
return;
}
MStatus status;
MObject transformNode = dag_path.transform(&status);
// This node has no transform - i.e., it's the world node
if (!status && status.statusCode() == MStatus::kInvalidParameter)
if (!status && status.statusCode() == MStatus::kInvalidParameter) {
return;
}
MFnDagNode transform(transformNode, &status);
if (!status) {
@ -306,22 +345,25 @@ get_transform(const MDagPath &dag_path, EggGroup *egg_group) {
MTransformationMatrix matrix(transform.transformationMatrix());
if (verbose >= 3) {
nout << " translation: " << matrix.translation(MSpace::kWorld)
<< "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " translation: " << matrix.translation(MSpace::kWorld)
<< "\n";
double d[3];
MTransformationMatrix::RotationOrder rOrder;
matrix.getRotation(d, rOrder, MSpace::kWorld);
nout << " rotation: ["
<< d[0] << ", "
<< d[1] << ", "
<< d[2] << "]\n";
mayaegg_cat.spam()
<< " rotation: ["
<< d[0] << ", "
<< d[1] << ", "
<< d[2] << "]\n";
matrix.getScale(d, MSpace::kWorld);
nout << " scale: ["
<< d[0] << ", "
<< d[1] << ", "
<< d[2] << "]\n";
mayaegg_cat.spam()
<< " scale: ["
<< d[0] << ", "
<< d[1] << ", "
<< d[2] << "]\n";
}
MMatrix mat = matrix.asMatrix();
@ -337,40 +379,49 @@ get_transform(const MDagPath &dag_path, EggGroup *egg_group) {
}
}
void MayaFile::
make_nurbs_surface(const MDagPath &dag_path,
MFnNurbsSurface &surface,
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::make_nurbs_surface
// Access: Private
// Description: Converts the indicated Maya NURBS surface to a
// corresponding egg structure, and attaches it to the
// indicated egg group.
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
EggGroup *egg_group) {
MStatus status;
string name = surface.name().asChar();
if (verbose >= 3) {
nout << " numCVs: "
<< surface.numCVsInU()
<< " * "
<< surface.numCVsInV()
<< "\n";
nout << " numKnots: "
<< surface.numKnotsInU()
<< " * "
<< surface.numKnotsInV()
<< "\n";
nout << " numSpans: "
<< surface.numSpansInU()
<< " * "
<< surface.numSpansInV()
<< "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " numCVs: "
<< surface.numCVsInU()
<< " * "
<< surface.numCVsInV()
<< "\n";
mayaegg_cat.spam()
<< " numKnots: "
<< surface.numKnotsInU()
<< " * "
<< surface.numKnotsInV()
<< "\n";
mayaegg_cat.spam()
<< " numSpans: "
<< surface.numSpansInU()
<< " * "
<< surface.numSpansInV()
<< "\n";
}
MayaShader *shader = _shaders.find_shader_for_node(surface.object());
if (polygon_output) {
if (MayaParameters::polygon_output) {
// If we want polygon output only, tesselate the NURBS and output
// that.
MTesselationParams params;
params.setFormatType(MTesselationParams::kStandardFitFormat);
params.setOutputType(MTesselationParams::kQuads);
params.setStdFractionalTolerance(polygon_tolerance);
params.setStdFractionalTolerance(MayaParameters::polygon_tolerance);
// We'll create the tesselation as a sibling of the NURBS surface.
// That way we inherit all of the transformations.
@ -416,8 +467,11 @@ make_nurbs_surface(const MDagPath &dag_path,
return;
}
/*
We don't use these variables currently.
MFnNurbsSurface::Form u_form = surface.formInU();
MFnNurbsSurface::Form v_form = surface.formInV();
*/
int u_degree = surface.degreeU();
int v_degree = surface.degreeV();
@ -536,20 +590,31 @@ make_nurbs_surface(const MDagPath &dag_path,
}
}
EggNurbsCurve *MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::make_trim_curve
// Access: Private
// Description: Converts the indicated Maya NURBS trim curve to a
// corresponding egg structure, and returns it, or NULL
// if there is a problem.
////////////////////////////////////////////////////////////////////
EggNurbsCurve *MayaToEggConverter::
make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
EggGroupNode *egg_group, int trim_curve_index) {
if (verbose >= 3) {
nout << "Trim curve:\n";
nout << " numCVs: "
<< curve.numCVs()
<< "\n";
nout << " numKnots: "
<< curve.numKnots()
<< "\n";
nout << " numSpans: "
<< curve.numSpans()
<< "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< "Trim curve:\n";
mayaegg_cat.spam()
<< " numCVs: "
<< curve.numCVs()
<< "\n";
mayaegg_cat.spam()
<< " numKnots: "
<< curve.numKnots()
<< "\n";
mayaegg_cat.spam()
<< " numSpans: "
<< curve.numSpans()
<< "\n";
}
MStatus status;
@ -567,7 +632,9 @@ make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
return (EggNurbsCurve *)NULL;
}
/*
MFnNurbsCurve::Form form = curve.form();
*/
int degree = curve.degree();
int cvs = curve.numCVs();
@ -575,10 +642,7 @@ make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
assert(knots == cvs + degree - 1);
char trim_str[20];
sprintf(trim_str, "trim%d", trim_curve_index);
assert(strlen(trim_str) < 20);
string trim_name = trim_str;
string trim_name = "trim" + format_string(trim_curve_index);
string vpool_name = nurbs_name + "." + trim_name;
EggVertexPool *vpool = new EggVertexPool(vpool_name);
@ -610,22 +674,32 @@ make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
return egg_curve;
}
void MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::make_nurbs_curve
// Access: Private
// Description: Converts the indicated Maya NURBS curve (a standalone
// curve, not a trim curve) to a corresponding egg
// structure and attaches it to the indicated egg group.
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
EggGroup *egg_group) {
MStatus status;
string name = curve.name().asChar();
if (verbose >= 3) {
nout << " numCVs: "
<< curve.numCVs()
<< "\n";
nout << " numKnots: "
<< curve.numKnots()
<< "\n";
nout << " numSpans: "
<< curve.numSpans()
<< "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " numCVs: "
<< curve.numCVs()
<< "\n";
mayaegg_cat.spam()
<< " numKnots: "
<< curve.numKnots()
<< "\n";
mayaegg_cat.spam()
<< " numSpans: "
<< curve.numSpans()
<< "\n";
}
MPointArray cv_array;
@ -641,7 +715,9 @@ make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
return;
}
/*
MFnNurbsCurve::Form form = curve.form();
*/
int degree = curve.degree();
int cvs = curve.numCVs();
@ -683,24 +759,34 @@ make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
}
}
void MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::make_polyset
// Access: Private
// Description: Converts the indicated Maya polyset to a bunch of
// EggPolygons and parents them to the indicated egg
// group.
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
EggGroup *egg_group, MayaShader *default_shader) {
MStatus status;
string name = mesh.name().asChar();
if (verbose >= 3) {
nout << " numPolygons: "
<< mesh.numPolygons()
<< "\n";
nout << " numVertices: "
<< mesh.numVertices()
<< "\n";
if (mayaegg_cat.is_spam()) {
mayaegg_cat.spam()
<< " numPolygons: "
<< mesh.numPolygons()
<< "\n";
mayaegg_cat.spam()
<< " numVertices: "
<< mesh.numVertices()
<< "\n";
}
if (mesh.numPolygons() == 0) {
if (verbose >= 2) {
nout << "Ignoring empty mesh " << name << "\n";
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring empty mesh " << name << "\n";
}
return;
}
@ -797,13 +883,29 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
}
EggGroup *MayaFile::
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_egg_group
// Access: Private
// Description: Returns the EggGroup corresponding to the indicated
// fully-qualified Maya path name. If there is not
// already an EggGroup corresponding to this Maya path,
// creates one and returns it.
//
// In this way we generate a unique EggGroup for each
// Maya node we care about about, and also preserve the
// Maya hierarchy sensibly.
////////////////////////////////////////////////////////////////////
EggGroup *MayaToEggConverter::
get_egg_group(const string &name, EggData &data) {
// If we have already encountered this pathname, return the
// corresponding EggGroup immediately.
Groups::const_iterator gi = _groups.find(name);
if (gi != _groups.end()) {
return (*gi).second;
}
// Otherwise, we have to create it. Do this recursively, so we
// create each node along the path.
EggGroup *egg_group;
if (name.empty()) {
@ -811,6 +913,9 @@ get_egg_group(const string &name, EggData &data) {
egg_group = (EggGroup *)NULL;
} else {
// Maya uses vertical bars to separate path components. Remove
// everything from the rightmost bar on; this will give us the
// parent's path name.
size_t bar = name.rfind("|");
string parent_name, local_name;
if (bar != string::npos) {

View File

@ -1,4 +1,4 @@
// Filename: mayaFile.h
// Filename: mayaToEggConverter.h
// Created by: drose (10Nov99)
//
////////////////////////////////////////////////////////////////////
@ -16,10 +16,13 @@
//
////////////////////////////////////////////////////////////////////
#ifndef MAYAFILE_H
#define MAYAFILE_H
#ifndef MAYATOEGGCONVERTER_H
#define MAYATOEGGCONVERTER_H
#include "pandatoolbase.h"
#include "somethingToEggConverter.h"
#include "mayaApi.h"
#include "mayaShaders.h"
#include "eggTextureCollection.h"
#include "distanceUnit.h"
@ -36,20 +39,31 @@ class MFnNurbsCurve;
class MFnMesh;
class MPointArray;
class MayaFile {
////////////////////////////////////////////////////////////////////
// Class : MayaToEggConverter
// Description : This class supervises the construction of an EggData
// structure from a single Maya file, or from the data
// already in the global Maya model space.
//
// Note that since the Maya API presents just one global
// model space, it is not possible to simultaneously
// load two distinct Maya files.
////////////////////////////////////////////////////////////////////
class MayaToEggConverter : public SomethingToEggConverter {
public:
MayaFile();
~MayaFile();
MayaToEggConverter(const string &program_name = "");
MayaToEggConverter(const MayaToEggConverter &copy);
virtual ~MayaToEggConverter();
bool init(const string &program);
bool read(const string &filename);
void make_egg(EggData &data);
virtual SomethingToEggConverter *make_copy();
static DistanceUnit get_units();
static CoordinateSystem get_coordinate_system();
virtual string get_name() const;
virtual string get_extension() const;
virtual bool convert_file(const Filename &filename);
bool convert_maya();
private:
bool traverse(EggData &data);
bool process_node(const MDagPath &dag_path, EggData &data);
void get_transform(const MDagPath &dag_path, EggGroup *egg_group);
@ -63,9 +77,11 @@ private:
const string &nurbs_name,
EggGroupNode *egg_group,
int trim_curve_index);
void make_nurbs_curve(const MDagPath &dag_path, const MFnNurbsCurve &curve,
void make_nurbs_curve(const MDagPath &dag_path,
const MFnNurbsCurve &curve,
EggGroup *group);
void make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
void make_polyset(const MDagPath &dag_path,
const MFnMesh &mesh,
EggGroup *egg_group,
MayaShader *default_shader = NULL);
@ -77,6 +93,7 @@ private:
public:
MayaShaders _shaders;
EggTextureCollection _textures;
PT(MayaApi) _maya;
};

View File

@ -0,0 +1,34 @@
// Filename: maya_funcs.I
// Created by: drose (15Apr02)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: MString output operator
// Description:
////////////////////////////////////////////////////////////////////
INLINE ostream &operator << (ostream &out, const MString &str) {
return out << str.asChar();
}
////////////////////////////////////////////////////////////////////
// Function: MVector output operator
// Description:
////////////////////////////////////////////////////////////////////
INLINE ostream &operator << (ostream &out, const MVector &vec) {
return out << vec.x << " " << vec.y << " " << vec.z;
}

View File

@ -16,6 +16,13 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: get_maya_attribute
// Description: A generic function to extract an attribute of some
// type from an MObject. This is used to implement
// get_bool_attribute(), etc.
////////////////////////////////////////////////////////////////////
template<class ValueType>
bool
get_maya_attribute(MObject &node, const string &attribute_name,
@ -23,21 +30,24 @@ get_maya_attribute(MObject &node, const string &attribute_name,
MStatus status;
MFnDependencyNode node_fn(node, &status);
if (!status) {
nout << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
mayaegg_cat.error()
<< "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
return false;
}
MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
if (!status) {
nout << "Object " << node_fn.name() << " does not support attribute "
<< attribute_name << "\n";
mayaegg_cat.error()
<< "Object " << node_fn.name() << " does not support attribute "
<< attribute_name << "\n";
return false;
}
MFnAttribute attr_fn(attr, &status);
if (!status) {
nout << "Attribute " << attribute_name << " on " << node_fn.name()
<< " is a " << attr.apiTypeStr() << ", not an Attribute.\n";
mayaegg_cat.error()
<< "Attribute " << attribute_name << " on " << node_fn.name()
<< " is a " << attr.apiTypeStr() << ", not an Attribute.\n";
return false;
}

View File

@ -0,0 +1,199 @@
// Filename: maya_funcs.cxx
// Created by: drose (16Feb00)
//
////////////////////////////////////////////////////////////////////
//
// 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 "maya_funcs.h"
#include "pre_maya_include.h"
#include <maya/MObject.h>
#include <maya/MAngle.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MStatus.h>
#include <maya/MFnStringData.h>
#include <maya/MFnNumericData.h>
#include "post_maya_include.h"
////////////////////////////////////////////////////////////////////
// Function: get_bool_attribute
// Description: Extracts the named boolean attribute from the
// MObject.
////////////////////////////////////////////////////////////////////
bool
get_bool_attribute(MObject &node, const string &attribute_name,
bool &value) {
if (!get_maya_attribute(node, attribute_name, value)) {
mayaegg_cat.error()
<< "Attribute " << attribute_name
<< " does not have an bool value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_bool_attribute
// Description: Extracts the named angle in degrees from the
// MObject.
////////////////////////////////////////////////////////////////////
bool
get_angle_attribute(MObject &node, const string &attribute_name,
double &value) {
MAngle maya_value;
if (!get_maya_attribute(node, attribute_name, maya_value)) {
mayaegg_cat.error()
<< "Attribute " << attribute_name
<< " does not have an angle value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
value = maya_value.asDegrees();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_vec2f_attribute
// Description: Extracts the named two-component vector from the
// MObject.
////////////////////////////////////////////////////////////////////
bool
get_vec2f_attribute(MObject &node, const string &attribute_name,
LVecBase2f &value) {
MStatus status;
MObject vec2f_object;
if (!get_maya_attribute(node, attribute_name, vec2f_object)) {
mayaegg_cat.error()
<< "Attribute " << attribute_name
<< " does not have a vec2f object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnNumericData data(vec2f_object, &status);
if (!status) {
mayaegg_cat.error()
<< "Attribute " << attribute_name << " is of type "
<< vec2f_object.apiTypeStr() << ", not a NumericData.\n";
return false;
}
status = data.getData(value[0], value[1]);
if (!status) {
mayaegg_cat.error()
<< "Unable to extract 2 floats from " << attribute_name
<< ", of type " << vec2f_object.apiTypeStr() << "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_vec2d_attribute
// Description: Extracts the named two-component vector from the
// MObject.
////////////////////////////////////////////////////////////////////
bool
get_vec2d_attribute(MObject &node, const string &attribute_name,
LVecBase2d &value) {
MStatus status;
MObject vec2d_object;
if (!get_maya_attribute(node, attribute_name, vec2d_object)) {
mayaegg_cat.error()
<< "Attribute " << attribute_name
<< " does not have a vec2d object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnNumericData data(vec2d_object, &status);
if (!status) {
mayaegg_cat.error()
<< "Attribute " << attribute_name << " is of type "
<< vec2d_object.apiTypeStr() << ", not a NumericData.\n";
return false;
}
status = data.getData(value[0], value[1]);
if (!status) {
mayaegg_cat.error()
<< "Unable to extract 2 doubles from " << attribute_name
<< ", of type " << vec2d_object.apiTypeStr() << "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_string_attribute
// Description: Extracts the named string attribute from the
// MObject.
////////////////////////////////////////////////////////////////////
bool
get_string_attribute(MObject &node, const string &attribute_name,
string &value) {
MStatus status;
MObject string_object;
if (!get_maya_attribute(node, attribute_name, string_object)) {
mayaegg_cat.error()
<< "Attribute " << attribute_name
<< " does not have an string object value.\n";
describe_maya_attribute(node, attribute_name);
return false;
}
MFnStringData data(string_object, &status);
if (!status) {
mayaegg_cat.error()
<< "Attribute " << attribute_name << " is of type "
<< string_object.apiTypeStr() << ", not a StringData.\n";
return false;
}
value = data.string().asChar();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: describe_maya_attribute
// Description: Writes some error output about the indicated Maya
// attribute.
////////////////////////////////////////////////////////////////////
void
describe_maya_attribute(MObject &node, const string &attribute_name) {
MStatus status;
MFnDependencyNode node_fn(node, &status);
if (!status) {
mayaegg_cat.error()
<< "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
return;
}
MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
if (!status) {
mayaegg_cat.error()
<< "Object " << node_fn.name() << " does not support attribute "
<< attribute_name << "\n";
return;
}
mayaegg_cat.error()
<< "Attribute " << attribute_name << " on object "
<< node_fn.name() << " has type " << attr.apiTypeStr() << "\n";
}

View File

@ -21,6 +21,7 @@
#include "pandatoolbase.h"
#include "luse.h"
#include "config_mayaegg.h"
#include "pre_maya_include.h"
#include <maya/MFnAttribute.h>
@ -65,14 +66,10 @@ describe_maya_attribute(MObject &node, const string &attribute_name);
// Also, we must define some output functions for Maya objects, since
// we can't use those built into Maya (which forward-defines the
// ostream type incorrectly).
INLINE ostream &operator << (ostream &out, const MString &str) {
return out << str.asChar();
}
INLINE ostream &operator << (ostream &out, const MVector &vec) {
return out << vec.x << " " << vec.y << " " << vec.z;
}
INLINE ostream &operator << (ostream &out, const MString &str);
INLINE ostream &operator << (ostream &out, const MVector &vec);
#include "maya_funcs.I"
#include "maya_funcs.T"
#endif

View File

@ -25,7 +25,7 @@
#define USE_MAYA yes
#define TARGET $[binary_name]
#define LOCAL_LIBS \
eggbase progbase
mayaegg eggbase progbase
#define OTHER_LIBS \
egg:c pandaegg:m \
linmath:c putil:c panda:m \
@ -36,10 +36,7 @@
m
#define SOURCES \
global_parameters.cxx global_parameters.h mayaFile.cxx mayaFile.h \
mayaShader.cxx mayaShader.h mayaShaders.cxx mayaShaders.h \
mayaToEgg.cxx mayaToEgg.h maya_funcs.I maya_funcs.cxx maya_funcs.h \
post_maya_include.h pre_maya_include.h
mayaToEgg.cxx mayaToEgg.h
#end bin_target

View File

@ -17,7 +17,9 @@
////////////////////////////////////////////////////////////////////
#include "mayaToEgg.h"
#include "global_parameters.h"
#include "mayaParameters.h"
#include "mayaToEggConverter.h"
#include "config_mayaegg.h"
////////////////////////////////////////////////////////////////////
// Function: MayaToEgg::Constructor
@ -31,9 +33,9 @@ MayaToEgg() :
add_units_options();
add_normals_options();
add_transform_options();
// add_texture_path_options();
// add_rel_dir_options();
// add_search_path_options(false);
add_texture_path_options();
add_rel_dir_options();
add_search_path_options(false);
set_program_description
("This program converts Maya model files to egg. Nothing fancy yet.");
@ -43,14 +45,14 @@ MayaToEgg() :
"Generate polygon output only. Tesselate all NURBS surfaces to "
"polygons via the built-in Maya tesselator. The tesselation will "
"be based on the tolerance factor given by -ptol.",
&MayaToEgg::dispatch_none, &polygon_output);
&MayaToEgg::dispatch_none, &MayaParameters::polygon_output);
add_option
("ptol", "tolerance", 0,
"Specify the fit tolerance for Maya polygon tesselation. The smaller "
"the number, the more polygons will be generated. The default is "
"0.01.",
&MayaToEgg::dispatch_double, NULL, &polygon_tolerance);
&MayaToEgg::dispatch_double, NULL, &MayaParameters::polygon_tolerance);
add_option
("notrans", "", 0,
@ -59,13 +61,13 @@ MayaToEgg() :
"one big transform space. Using this option doesn't change the "
"position of objects in the scene, just the number of explicit "
"transforms appearing in the resulting egg file.",
&MayaToEgg::dispatch_none, &ignore_transforms);
&MayaToEgg::dispatch_none, &MayaParameters::ignore_transforms);
add_option
("v", "", 0,
"Increase verbosity. More v's means more verbose.",
&MayaToEgg::dispatch_count, NULL, &verbose);
verbose = 0;
&MayaToEgg::dispatch_count, NULL, &_verbose);
_verbose = 0;
}
////////////////////////////////////////////////////////////////////
@ -75,31 +77,43 @@ MayaToEgg() :
////////////////////////////////////////////////////////////////////
void MayaToEgg::
run() {
nout << "Initializing Maya.\n";
if (!_maya.init(_program_name)) {
nout << "Unable to initialize Maya.\n";
exit(1);
// Set the verbose level by using Notify.
if (_verbose >= 3) {
mayaegg_cat->set_severity(NS_spam);
} else if (_verbose >= 2) {
mayaegg_cat->set_severity(NS_debug);
} else if (_verbose >= 1) {
mayaegg_cat->set_severity(NS_info);
}
if (!_maya.read(_input_filename.c_str())) {
nout << "Error reading " << _input_filename << ".\n";
nout << "Initializing Maya.\n";
MayaToEggConverter converter(_program_name);
if (!converter._maya->is_valid()) {
nout << "Unable to initialize Maya.\n";
exit(1);
}
// Set the coordinate system to match Maya's.
if (!_got_coordinate_system) {
_coordinate_system = MayaFile::get_coordinate_system();
_coordinate_system = converter._maya->get_coordinate_system();
}
_data.set_coordinate_system(_coordinate_system);
// Get the units from the Maya file, if the user didn't override.
if (_input_units == DU_invalid) {
_input_units = MayaFile::get_units();
_input_units = converter._maya->get_units();
}
_maya.make_egg(_data);
converter.set_egg_data(&_data, false);
converter.set_texture_path_convert(_texture_path_convert, _make_rel_dir);
if (!converter.convert_file(_input_filename)) {
nout << "Errors in conversion.\n";
exit(1);
}
write_egg_file();
nout << "\n";
}

View File

@ -20,7 +20,6 @@
#define MAYATOEGG_H
#include "pandatoolbase.h"
#include "mayaFile.h"
#include "somethingToEgg.h"
////////////////////////////////////////////////////////////////////
@ -30,10 +29,11 @@
class MayaToEgg : public SomethingToEgg {
public:
MayaToEgg();
~MayaToEgg();
void run();
MayaFile _maya;
int _verbose;
};
#endif

View File

@ -1,7 +1,8 @@
#begin lib_target
#define TARGET ptloader
#define BUILDING_DLL BUILDING_PTLOADER
#define LOCAL_LIBS xfile fltegg flt lwoegg lwo converter pandatoolbase
#define LOCAL_LIBS \
xfile fltegg flt lwoegg lwo mayaegg converter pandatoolbase
#define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
@ -16,6 +17,9 @@
#define USE_DX yes
#endif
// If we've got Maya, link in the Maya libraries.
#define USE_MAYA yes
#define SOURCES \
config_ptloader.cxx config_ptloader.h \
loaderFileTypePandatool.cxx loaderFileTypePandatool.h

View File

@ -29,6 +29,11 @@
#include "xFileToEggConverter.h"
#endif
#ifdef HAVE_MAYA
#include "config_mayaegg.h"
#include "mayaToEggConverter.h"
#endif
#include "dconfig.h"
#include "loaderFileTypeRegistry.h"
#include "eggData.h"
@ -72,4 +77,10 @@ init_libptloader() {
XFileToEggConverter *xfile = new XFileToEggConverter;
reg->register_type(new LoaderFileTypePandatool(xfile));
#endif
#ifdef HAVE_MAYA
init_libmayaegg();
MayaToEggConverter *maya = new MayaToEggConverter;
reg->register_type(new LoaderFileTypePandatool(maya));
#endif
}