polyX3DExporter/polyX3DWriter.cpp

polyX3DExporter/polyX3DWriter.cpp
//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+
//
//
//General Includes
//
#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
#include <maya/MDagPath.h>
#include <maya/MIntArray.h>
#include <maya/MFnSet.h>
#include <maya/MItDependencyGraph.h>
#include <maya/MPlug.h>
//Iterator Includes
//
#include <maya/MItMeshPolygon.h>
//polyX3DWriter.cpp
#include "polyX3DWriter.h"
//Macros
//used as the default color for vertices which have no color assigned
//
#define DEFAULT_COLOR "0.2 0.2 0.2"
//used as default values for the Material tag when outputting a texture
//
#define DIFFUSE_COLOR "0 0 0"
#define SHININESS "0.8"
#define SPECULAR_COLOR "0.5 0.5 0.5"
//flags used to indicate which tags have been outputted already, so to
//minimize data duplication
//
#define COORDINATE_FLAG 0x0001
#define NORMAL_FLAG 0x0010
#define TEXTURE_FLAG 0x0100
#define COLOR_FLAG 0x1000
//number of spaces per tab
#define INITIAL_TAB_COUNT 2
polyX3DWriter::polyX3DWriter(const MDagPath& dagPath, MStatus& status):
polyWriter(dagPath, status),
fTagFlags(0),
fInitialTabCount(INITIAL_TAB_COUNT)
//Summary: creates and initializes an object of this class
//Args : dagPath - the DAG path of the current node
// status - will be set to MStatus::kSuccess if the constructor was
// successful; MStatus::kFailure otherwise
{
}
polyX3DWriter::~polyX3DWriter()
{
//Summary: destructor method - does nothing
//
}
MStatus polyX3DWriter::extractGeometry()
//Summary: extracts main geometry as well as the current UV set and UV set
// coordinates
{
if (MStatus::kFailure == polyWriter::extractGeometry()) {
}
if (MStatus::kFailure == fMesh->getUVs(fUArray, fVArray, &fCurrentUVSetName)) {
MGlobal::displayError("MFnMesh::getUVs");
}
}
MStatus polyX3DWriter::writeToFile(ostream& os)
//Summary: outputs the geometry of this polygonal mesh in X3D compliant format
//Args : os - an output stream to write to
// tabCount - the initial number of tabs to print
//Returns: MStatus::kSuccess if the method succeeds
// MStatus::kFailure if the method fails
{
MGlobal::displayInfo("Exporting " + fMesh->partialPathName());
unsigned int setCount = fPolygonSets.length();
if (0 == setCount) {
} else if (1 == setCount) {
if (MStatus::kFailure == outputSets(os)) {
}
} else {
outputTabs(os, INITIAL_TAB_COUNT);
fInitialTabCount++;
os << "<Group DEF=\"" << fMesh->partialPathName() << "\">\n";
if (MStatus::kFailure == outputSets(os)) {
}
outputTabs(os, INITIAL_TAB_COUNT);
os << "</Group>\n";
}
}
MStatus polyX3DWriter::outputSingleSet (ostream& os, MString setName, MIntArray faces, MString textureName) {
//Summary: outputs a single set of polygons grouped under a Shape tag
//Args : os - an output stream to write to
// shapeName - the value for the DEF attribute
// faces - an MIntArray containing the indices of the faces to include
// in this shape
// textureName - the full path for the texture file
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
if (0 == fPolygonSets.length()) {
} else if (1 == fPolygonSets.length()) {
setName = fMesh->partialPathName();
} else {
setName = fMesh->partialPathName() + "_" + setName;
}
return outputX3DShapeTag (os, setName, faces, textureName, fInitialTabCount);
}
MStatus polyX3DWriter::outputX3DShapeTag(ostream & os,
const MString shapeName,
const MIntArray& faces,
const MString textureName,
const unsigned int tabCount)
//Summary: outputs the X3D Shape tag with the DEF attribute
//Args : os - an output stream to write to
// shapeName - the value for the DEF attribute
// faces - an MIntArray containing the indices of the faces to include
// in this shape
// textureName - the full path for the texture file
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
outputTabs(os, tabCount);
os << "<Shape DEF=\"" << shapeName << "\">\n";
if (MStatus::kFailure == outputX3DAppearanceTag(os, textureName, tabCount + 1)) {
}
if (MStatus::kFailure == outputX3DIndexedFaceSetTag(os, faces, textureName, tabCount + 1)) {
}
outputTabs(os, tabCount);
os << "</Shape>\n";
}
MStatus polyX3DWriter::outputX3DAppearanceTag(ostream & os,
const MString textureName,
const unsigned int tabCount)
//Summary: outputs the X3D Appearance Tag. If textureName is an empty string,
// outputs the default Material tag; otherwise outputs a Material tag
// with diffuseColor, shininess, and specularColor values set, along
// with an ImageTexture tag with the url attribute value set to
// textureName
//Args : os - an output stream to write to
// textureName - the full path of the texture file
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
outputTabs(os, tabCount);
//No texture name given, output default apperance and material tags
//
if (textureName == MString("")) {
os << "<Appearance><Material/></Appearance>\n";
//Texture name was given, output an ImageTexture tag with the texture name
//as the value of the url attribute, and output default values for the
//diffuseColor, shininess, and specularColor of the material node
//
} else {
os << "<Appearance>\n";
outputTabs(os, tabCount + 1);
os << "<ImageTexture url=\"" << textureName << "\"/>\n";
outputTabs(os, tabCount + 1);
os << "<Material diffuseColor=\"" << DIFFUSE_COLOR
<< "\" shininess=\"" << SHININESS
<< "\" specularColor=\"" << SPECULAR_COLOR
<< "\"/>\n";
outputTabs(os, tabCount);
os << "</Appearance>\n";
}
}
MStatus polyX3DWriter::outputX3DIndexedFaceSetTag(ostream & os,
const MIntArray& faces,
const MString textureName,
const unsigned int tabCount)
//Summary: outputs the X3D IndexedFaceSet tag along with the Coordinate and
// Normal tags. If textureName is an empty string, also outputs the
// Color tag and IndexedFaceSet's colorIndex and colorPerVertex
// attributes; otherwise outputs the TextureCoordinate tag and
// IndexedFaceSet's texCoordIndex attribute
//Args : os - an output stream to write to
// faces - an MIntArray containing the indices of the faces to include
// in this IndexedFaceSet
// textureName - the full path for the texture file
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
outputTabs(os, tabCount);
os << "<IndexedFaceSet coordIndex=\"";
unsigned int faceCount = faces.length();
//if there are no faces to output return an error status
//
if (0 == faceCount) {
}
MStatus status;
//general purpose counters
//
unsigned int i, j, indexCount;
//general int array storage
//
MIntArray indexList;
//For every face in the faces array, retrieve and output its vertices.
//getPolygonVertices() returns the indices of the vertices of a given face,
//and orders the vertex indices in the array in the manner required for the
//X3D IndexedFaceSet tag. Note, these indices refer to the array fVertexArray.
//
for (i = 0; i < faceCount; i++) {
indexCount = fMesh->polygonVertexCount(faces[i], &status);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::polygonVertexCount");
}
//store those vertices for face[i] and output them
//
status = fMesh->getPolygonVertices (faces[i], indexList);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::getPolygonVertices");
}
for (j = 0; j < indexCount; j++) {
os << indexList[j] << " ";
}
os << "-1 ";
}
//For every face in the faces array, retrieve and output its vertex normals.
//getNormalIDs() returns the indices of the normals of a given face. Note,
//these indices refer to the array fNormalArray.
//
os << "\" normalPerVertex=\"true\" normalIndex=\"";
for (i = 0; i < faceCount; i++) {
//store the vertex normals for face[i]
//
status = fMesh->getFaceNormalIds (faces[i], indexList);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::getFaceNormalIds");
}
//determine the number of vertex normals for face[i]
//and output them
indexCount = indexList.length();
for (j = 0; j < indexCount; j++) {
os << indexList[j] << " ";
}
os << "-1 ";
}
os << "\" ";
//If a texture name is not given, output colorIndex attribute
if (textureName == MString("")) {
os << "colorPerVertex=\"true\" ";
//output the color indices for each per polygon vertex. These indices
//refer to the array fColorArray
//
os << "colorIndex=\"";
int colorIndex = 0;
for (i = 0; i < faceCount; i++) {
indexCount = fMesh->polygonVertexCount(faces[i], &status);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::polygonVertexCount");
}
for (j = 0; j < indexCount; j++) {
if (MStatus::kFailure == fMesh->getFaceVertexColorIndex(faces[i], j, colorIndex)) {
MGlobal::displayError("MFnMesh::getFaceVertexColorIndex");
}
os << colorIndex << " ";
}
os << "-1 ";
}
os << "\">\n";
//output the X3D color tag to correspond with the indices
//
if (MStatus::kFailure == outputX3DColorTag(os, tabCount + 1)) {
}
//A texture name was given, output the texCoordIndex attribute
//
} else {
os << " texCoordIndex=\"";
//output the uv indicies for each polygon per vertex. These indices
//refer to the arrays fUArray and fVArray
//
for (i = 0; i < faceCount; i++) {
indexCount = fMesh->polygonVertexCount(faces[i], &status);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::polygonVertexCount");
}
for (j = 0; j < indexCount; j++) {
int uvID;
status = fMesh->getPolygonUVid(faces[i], j, uvID, &fCurrentUVSetName);
if (MStatus::kFailure == status) {
MGlobal::displayError("MFnMesh::getPolygonUVid");
}
os << uvID << " ";
}
os << "-1 ";
}
os << "\">\n";
//output the X3D TextureCoordinateTag to correspond with the indices
//
if (MStatus::kFailure == outputX3DTextureCoordinateTag(os, tabCount + 1)) {
}
}
//output the vertex coordinates using the X3D Coordinate tag and
//output the vertex normals using the X3D Normal tag
//
if (MStatus::kFailure == outputX3DCoordinateTag(os, tabCount + 1)
|| MStatus::kFailure == outputX3DNormalTag(os, tabCount + 1)) {
}
outputTabs(os, tabCount);
os << "</IndexedFaceSet>\n";
}
MStatus polyX3DWriter::outputX3DCoordinateTag(ostream & os,
const unsigned int tabCount)
//Summary: outputs the X3D Coordinate tag with the DEF attribute if the tag
// has not been previously output for this polygonal mesh; with the
// USE attribute otherwise
//Args : os - an output stream to write to
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
unsigned int vertexCount = fVertexArray.length();
if (0 == vertexCount) {
}
outputTabs(os, tabCount);
//tag has already been output for this mesh, so just re-use that tag
//
if (fTagFlags & COORDINATE_FLAG) {
os << "<Coordinate USE=\"" << fMesh->partialPathName() << "_coordinates";
//tag has not been output for this mesh, so define a new tag with the
//necessary data
//
} else {
fTagFlags |= COORDINATE_FLAG;
os << "<Coordinate DEF=\"" << fMesh->partialPathName() << "_coordinates\" point=\"";
unsigned int i;
for (i = 0; i < vertexCount; i++) {
os << fVertexArray[i].x << " "
<< fVertexArray[i].y << " "
<< fVertexArray[i].z << ", ";
}
}
os << "\"/>\n";
}
MStatus polyX3DWriter::outputX3DNormalTag(ostream & os,
const unsigned int tabCount)
//Summary: outputs the X3D Normal tag with the DEF attribute if the Normal tag
// has not been previously output for this polygonal mesh; with the
// USE attribute otherwise
//Args : os - an output stream to write to
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
unsigned int normalCount = fNormalArray.length();
if (0 == normalCount) {
}
outputTabs(os, tabCount);
//tag has already been output for this mesh, so just re-use that tag
//
if (fTagFlags & NORMAL_FLAG) {
os << "<Normal USE=\"" << fMesh->partialPathName() << "_normals";
//tag has not been output for this mesh, so define a new tag with the
//necessary data
//
} else {
fTagFlags |= NORMAL_FLAG;
os << "<Normal DEF=\"" << fMesh->partialPathName() << "_normals\" vector=\"";
unsigned int i;
for (i = 0; i < normalCount; i++) {
os << fNormalArray[i].x << " "
<< fNormalArray[i].y << " "
<< fNormalArray[i].z << ", ";
}
}
os << "\"/>\n";
}
MStatus polyX3DWriter::outputX3DTextureCoordinateTag(ostream & os,
const unsigned int tabCount)
//Summary: outputs the X3D TextureCoordinate tag with the DEF attribute if the
// tag has not been previously output for this polygonal mesh; with
// the USE attribute otherwise
//Args : os - an output stream to write to
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
unsigned int uvCount = fUArray.length();
if (0 == uvCount) {
}
outputTabs(os, tabCount);
//tag has already been output for this mesh, so just re-use that tag
//
if (fTagFlags & TEXTURE_FLAG) {
os << "<TextureCoordinate USE=\"" << fMesh->partialPathName() << "_texCoordinates";
//tag has not been output for this mesh, so define a new tag with the
//necessary data
//
} else {
fTagFlags |= TEXTURE_FLAG;
os << "<TextureCoordinate DEF=\"" << fMesh->partialPathName() << "_texCoordinates\" point=\"";
unsigned int i;
for (i = 0; i < uvCount; i++) {
os << fUArray[i] << " " << fVArray[i] << ", ";
}
}
os << "\"/>\n";
}
MStatus polyX3DWriter::outputX3DColorTag(ostream & os,
const unsigned int tabCount)
//Summary: outputs the X3D Color tag with the DEF attribute if the tag has not
// been previously output for this polygonal mesh; with the USE
// attribute otherwise
//Args : os - an output stream to write to
// tabCount - the number of tabs to preceed this tag
//Returns: MStatus::kSuccess if the method successfully outputs this tag;
// MStatus::kFailure otherwise
{
unsigned int colorCount = fColorArray.length();
if (0 == colorCount) {
}
outputTabs(os, tabCount);
//tag has already been output for this mesh, so just re-use that tag
//
if (fTagFlags & COLOR_FLAG) {
os << "<Color USE=\"" << fMesh->partialPathName() << "_colors";
//tag has not been output for this mesh, so define a new tag with the
//necessary data
//
} else {
fTagFlags |= COLOR_FLAG;
os << "<Color DEF=\"" << fMesh->partialPathName() << "_colors\" color=\"";
unsigned int i;
for (i = 0; i < colorCount; i++) {
//an rgb value of -1 -1 -1 in Maya indicates no color, so if any
//component is not -1, color info is present. Note: only need to check
//r, g, or b; r was chosen arbitrarily
//
if (-1 != fColorArray[i].r) {
os << fColorArray[i].r << " "
<< fColorArray[i].g << " "
<< fColorArray[i].b << ", ";
//use default coloring
//
} else {
os << DEFAULT_COLOR << ", ";
}
}
}
os << "\"/>\n";
}