support projected textures

This commit is contained in:
David Rose 2003-03-04 03:45:15 +00:00
parent d72425f45d
commit 81006f1eb4
8 changed files with 230 additions and 22 deletions

View File

@ -43,6 +43,9 @@ MayaApi::
MayaApi(const string &program_name) {
// Beginning with Maya4.5, the call to initialize seems to change
// the current directory! Yikes!
// Furthermore, the current directory may change during the call to
// any Maya function! Egad!
Filename cwd = ExecutionEnvironment::get_cwd();
MStatus stat = MLibrary::initialize((char *)program_name.c_str());
@ -52,6 +55,11 @@ MayaApi(const string &program_name) {
maya_cat.warning()
<< "Unable to restore current directory to " << cwd
<< " after initializing Maya.\n";
} else {
if (maya_cat.is_debug()) {
maya_cat.debug()
<< "Restored current directory to " << cwd << "\n";
}
}
if (!stat) {

View File

@ -19,6 +19,7 @@
#include "mayaShader.h"
#include "maya_funcs.h"
#include "config_maya.h"
#include "string_utils.h"
#include "pset.h"
#include "pre_maya_include.h"
@ -43,6 +44,7 @@ MayaShader(MObject engine) {
_transparency = 0.0;
_has_texture = false;
_projection_type = PT_off;
_coverage.set(1.0, 1.0);
_translate_frame.set(0.0, 0.0);
@ -114,6 +116,38 @@ compute_texture_matrix() const {
LMatrix3d::translate_mat(trans);
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::has_projection
// Access: Public
// Description: Returns true if the shader has a projection in effect.
////////////////////////////////////////////////////////////////////
bool MayaShader::
has_projection() const {
return (_projection_type != PT_off);
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::project_uv
// Access: Public
// Description: If the shader has a projection (has_projection()
// returns true), this computes the appropriate UV
// corresponding to the indicated 3-d point.
////////////////////////////////////////////////////////////////////
TexCoordd MayaShader::
project_uv(const LPoint3d &point) const {
switch (_projection_type) {
case PT_planar:
{
LPoint3d p2d = point * _projection_matrix;
return TexCoordd(p2d[0], p2d[1]);
//return TexCoordd((p2d[0] + 1.0) / 2.0, (p2d[1] + 1.0) / 2.0);
}
default:
return TexCoordd(0.0, 0.0);
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::output
// Access: Public
@ -168,7 +202,7 @@ reset_maya_texture(const Filename &texture) {
////////////////////////////////////////////////////////////////////
// Function: MayaShader::read_surface_shader
// Access: Public
// Access: Private
// Description: Extracts out the shading information from the Maya
// surface shader.
////////////////////////////////////////////////////////////////////
@ -196,6 +230,19 @@ read_surface_shader(MObject shader) {
}
}
// Or maybe a connection to outColor. Not sure how this differs
// from just color, but empirically it seems that either might be
// used.
MPlug out_color_plug = shader_fn.findPlug("outColor");
if (!out_color_plug.isNull()) {
MPlugArray color_pa;
out_color_plug.connectedTo(color_pa, true, false);
for (size_t i = 0; i < color_pa.length(); i++) {
read_surface_color(color_pa[0].node());
}
}
// Also try to get the ordinary color directly from the surface
// shader.
if (shader.hasFn(MFn::kLambert)) {
@ -218,16 +265,15 @@ read_surface_shader(MObject shader) {
////////////////////////////////////////////////////////////////////
// Function: MayaShader::read_surface_color
// Access: Public
// Access: Private
// Description: Determines the surface color specified by the shader.
// This includes texturing and other advanced shader
// properties.
////////////////////////////////////////////////////////////////////
void MayaShader::
read_surface_color(MObject color) {
_color_object = new MObject(color);
if (color.hasFn(MFn::kFileTexture)) {
_color_object = new MObject(color);
string filename;
_has_texture = get_string_attribute(color, "fileTextureName", filename);
if (_has_texture) {
@ -247,6 +293,29 @@ read_surface_color(MObject color) {
get_vec2f_attribute(color, "offset", _offset);
get_angle_attribute(color, "rotateUV", _rotate_uv);
} else if (color.hasFn(MFn::kProjection)) {
// This is a projected texture. We will have to step one level
// deeper to find the actual texture.
MFnDependencyNode projection_fn(color);
MPlug image_plug = projection_fn.findPlug("image");
if (!image_plug.isNull()) {
MPlugArray image_pa;
image_plug.connectedTo(image_pa, true, false);
for (size_t i = 0; i < image_pa.length(); i++) {
read_surface_color(image_pa[0].node());
}
}
if (!get_mat4d_attribute(color, "placementMatrix", _projection_matrix)) {
_projection_matrix = LMatrix4d::ident_mat();
}
string type;
if (get_enum_attribute(color, "projType", type)) {
set_projection_type(type);
}
} else {
// This shader wasn't understood.
if (maya_cat.is_debug()) {
@ -266,3 +335,29 @@ read_surface_color(MObject color) {
}
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::set_projection_type
// Access: Private
// Description: Sets up the shader to apply UV's according to the
// indicated projection type.
////////////////////////////////////////////////////////////////////
void MayaShader::
set_projection_type(const string &type) {
if (cmp_nocase(type, "planar") == 0) {
_projection_type = PT_planar;
// The Planar projection normally projects to a range (-1, 1) in
// both axes. Scale this into our UV range of (0, 1).
_projection_matrix = _projection_matrix * LMatrix4d(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.0, 1.0);
} else {
// Other projection types are currently unimplemented by the
// converter.
maya_cat.error()
<< "Don't know how to handle type " << type << " projections.\n";
}
}

View File

@ -40,6 +40,8 @@ public:
~MayaShader();
LMatrix3d compute_texture_matrix() const;
bool has_projection() const;
TexCoordd project_uv(const LPoint3d &point) const;
void output(ostream &out) const;
bool reset_maya_texture(const Filename &texture);
@ -53,6 +55,20 @@ public:
bool _has_texture;
Filename _texture;
enum ProjectionType {
PT_off,
PT_planar,
PT_spherical,
PT_cylindrical,
PT_ball,
PT_cubic,
PT_triplanar,
PT_concentric,
PT_perspective,
};
ProjectionType _projection_type;
LMatrix4d _projection_matrix;
LVector2f _coverage;
LVector2f _translate_frame;
double _rotate_frame;
@ -71,6 +87,7 @@ private:
bool read_surface_shader(MObject shader);
void read_surface_color(MObject color);
void set_projection_type(const string &type);
};
INLINE ostream &operator << (ostream &out, const MayaShader &shader) {

View File

@ -30,6 +30,8 @@
#include <maya/MFnAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnMatrixData.h>
#include <maya/MMatrix.h>
#include "post_maya_include.h"
////////////////////////////////////////////////////////////////////
@ -66,6 +68,29 @@ get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: has_attribute
// Description: Returns true if the node has the indicated attribute,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool
has_attribute(MObject &node, const string &attribute_name) {
MStatus status;
MFnDependencyNode node_fn(node, &status);
if (!status) {
maya_cat.error()
<< "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
return false;
}
node_fn.attribute(attribute_name.c_str(), &status);
if (!status) {
// No such attribute.
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_bool_attribute
// Description: Extracts the named boolean attribute from the
@ -74,6 +99,12 @@ get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug) {
bool
get_bool_attribute(MObject &node, const string &attribute_name,
bool &value) {
if (!has_attribute(node, attribute_name)) {
// For bool attributes only, we assume if the attribute is absent
// it's the same thing as being false.
return false;
}
if (!get_maya_attribute(node, attribute_name, value)) {
maya_cat.error()
<< "Attribute " << attribute_name
@ -178,6 +209,36 @@ get_vec2d_attribute(MObject &node, const string &attribute_name,
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_mat4d_attribute
// Description: Extracts the named 4x4 matrix from the MObject.
////////////////////////////////////////////////////////////////////
bool
get_mat4d_attribute(MObject &node, const string &attribute_name,
LMatrix4d &value) {
MStatus status;
MObject matrix;
if (!get_maya_attribute(node, attribute_name, matrix)) {
return false;
}
MFnMatrixData matrix_data(matrix, &status);
if (!status) {
maya_cat.error()
<< "Attribute " << attribute_name << " is of type "
<< node.apiTypeStr() << ", not a Matrix.\n";
return false;
}
const MMatrix &mat = matrix_data.matrix();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
value(i, j) = mat(i, j);
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: get_enum_attribute
// Description: Extracts the enum attribute from the MObject as a

View File

@ -48,6 +48,9 @@ bool
set_maya_attribute(MObject &node, const string &attribute_name,
ValueType &value);
bool
has_attribute(MObject &node, const string &attribute_name);
bool
get_bool_attribute(MObject &node, const string &attribute_name,
bool &value);
@ -64,6 +67,10 @@ bool
get_vec2d_attribute(MObject &node, const string &attribute_name,
LVecBase2d &value);
bool
get_mat4d_attribute(MObject &node, const string &attribute_name,
LMatrix4d &value);
bool
get_enum_attribute(MObject &node, const string &attribute_name,
string &value);

View File

@ -1209,12 +1209,29 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
egg_poly->set_bface_flag(double_sided);
// Determine the shader for this particular polygon.
MayaShader *shader = NULL;
int index = pi.index();
nassertv(index >= 0 && index < (int)poly_shader_indices.length());
int shader_index = poly_shader_indices[index];
if (shader_index != -1) {
nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
MObject engine = shaders[shader_index];
shader =
_shaders.find_shader_for_shading_engine(engine);
} else if (default_shader != (MayaShader *)NULL) {
shader = default_shader;
}
// Get the vertices for the polygon.
long num_verts = pi.polygonVertexCount();
for (long i = 0; i < num_verts; i++) {
EggVertex vert;
MPoint p = pi.point(i, MSpace::kWorld);
vert.set_pos(LPoint3d(p[0], p[1], p[2]));
LPoint3d p3d(p[0], p[1], p[2]);
vert.set_pos(p3d);
MVector n;
status = pi.getNormal(i, n, MSpace::kWorld);
@ -1224,7 +1241,13 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
vert.set_normal(LVector3d(n[0], n[1], n[2]));
}
if (pi.hasUVs()) {
if (shader->has_projection()) {
// If the shader has a projection, use it instead of the
// polygon's built-in UV's.
vert.set_uv(shader->project_uv(p3d));
} else if (pi.hasUVs()) {
// Get the UV's from the polygon.
float2 uvs;
status = pi.getUV(i, uvs);
if (!status) {
@ -1249,21 +1272,9 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
egg_poly->add_vertex(vpool->create_unique_vertex(vert));
}
// Determine the shader for this particular polygon.
int index = pi.index();
nassertv(index >= 0 && index < (int)poly_shader_indices.length());
int shader_index = poly_shader_indices[index];
if (shader_index != -1) {
nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
MObject engine = shaders[shader_index];
MayaShader *shader =
_shaders.find_shader_for_shading_engine(engine);
if (shader != (MayaShader *)NULL) {
set_shader_attributes(*egg_poly, *shader);
}
} else if (default_shader != (MayaShader *)NULL) {
set_shader_attributes(*egg_poly, *default_shader);
// Now apply the shader.
if (shader != (MayaShader *)NULL) {
set_shader_attributes(*egg_poly, *shader);
}
pi.next();

View File

@ -19,6 +19,7 @@
#include "mayaToEgg.h"
#include "mayaToEggConverter.h"
#include "config_mayaegg.h"
#include "config_maya.h" // for maya_cat
////////////////////////////////////////////////////////////////////
// Function: MayaToEgg::Constructor
@ -78,13 +79,20 @@ void MayaToEgg::
run() {
// Set the verbose level by using Notify.
if (_verbose >= 3) {
maya_cat->set_severity(NS_spam);
mayaegg_cat->set_severity(NS_spam);
} else if (_verbose >= 2) {
maya_cat->set_severity(NS_debug);
mayaegg_cat->set_severity(NS_debug);
} else if (_verbose >= 1) {
maya_cat->set_severity(NS_info);
mayaegg_cat->set_severity(NS_info);
}
// Let's open the output file before we initialize Maya, since Maya
// now has a nasty habit of changing the current directory.
get_output();
nout << "Initializing Maya.\n";
MayaToEggConverter converter(_program_name);
if (!converter.open_api()) {

View File

@ -17,8 +17,9 @@
////////////////////////////////////////////////////////////////////
#include "withOutputFile.h"
#include "executionEnvironment.h"
#include <notify.h>
#include "notify.h"
////////////////////////////////////////////////////////////////////
// Function: WithOutputFile::Constructor