|
From: Mike D. <o3d...@us...> - 2005-01-28 20:27:09
|
Update of /cvsroot/grappelmann/spaceplane In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16779 Added Files: simple_sphere.cpp simple_sphere.h x3d_loader.cpp x3d_loader.h Log Message: - some refactoring - simple sphere scene object --- NEW FILE: x3d_loader.cpp --- // $Id: x3d_loader.cpp,v 1.1 2005/01/28 20:26:58 o3dozone Exp $ #include "x3d_loader.h" X3DLoader::X3DLoader() { } SceneObject* X3DLoader::loadModel(const string filename) { SceneObject* sceneRoot = NULL; if((sceneRoot = _parseX3DFile(filename.c_str())) == NULL) { cout << "error parsing x3d file" << endl; abort(); } return sceneRoot; } SceneObject* X3DLoader::_parseX3DFile(const char* filename) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); cout << "Error during initialization [" << message << "]" << endl; XMLString::release(&message); return NULL; } XercesDOMParser* parser = new XercesDOMParser(); parser->setValidationScheme(XercesDOMParser::Val_Always); // optional. //parser->setDoNamespaces(scene); // optional ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase(); parser->setErrorHandler(errHandler); SceneObject* sceneRoot = NULL; try { parser->parse(filename); DOMDocument* domDocument = parser->getDocument(); if(domDocument->getDocumentElement() == NULL) { cout << "empty document" << endl; return NULL; } else if((sceneRoot = _convertDOMNode(domDocument->getDocumentElement())) == NULL) { cout << "couldn't dump dom document" << endl; return NULL; } } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); cout << "Exception message is [" << message << "]" << endl; XMLString::release(&message); return NULL; } catch (const DOMException& toCatch) { char* message = XMLString::transcode(toCatch.msg); cout << "Exception message is [" << message << "]" << endl; XMLString::release(&message); return NULL; } catch (...) { cout << "Unexpected Exception \n" ; return NULL; } delete parser; delete errHandler; return sceneRoot; } SceneObject* X3DLoader::_convertDOMNode(DOMNode* domNode, SceneObject* parent, long curLevel) { if(domNode == NULL) { cout << "<X3DLoader::_convertDOMNode>\tempty DOM node" << endl; return NULL; } // some sensible defaults if(parent == NULL) { parent = new SceneObject(); } SceneObject* scene = NULL; try { if(domNode->getNodeType() == DOMNode::ELEMENT_NODE) { cout << "[" << curLevel << "] node type [" << domNode->getNodeType() << "] node name [" << XMLString::transcode(domNode->getNodeName()) << "]" << endl; // value [" << XMLString::transcode(domNode->getNodeValue()) << "]" << endl; if(domNode->getNodeValue() != NULL) { cout << "[" << curLevel << "] value [" << XMLString::transcode(domNode->getNodeValue()) << "]" << endl; } // find the dom node attributes DOMNamedNodeMap* attributes = domNode->getAttributes(); if(attributes != NULL) { cout << "[" << curLevel << "] dumping attributes" << endl; // get a scene object from the DOM Node // *** NOTE *** slightly dodgy, but handleChildren gets set in the _createSceneObjectFromDOMNode call below bool handleChildren = true; scene = _createSceneObjectFromDOMNode(domNode, handleChildren); if(scene == NULL) { cout << "<X3DLoader::_convertDOMNode>\tempty scene" << endl; // *** NOTE *** This is a little 'hack', so we can avoid a scene with mostly dummy nodes scene = parent; //return NULL; } cout << "[" << curLevel << "] dumping attributes complete" << endl; if(handleChildren) { // dump this element's children first DOMNode* curChild = domNode->getFirstChild(); while(curChild != NULL) { // dump the child SceneObject* child = _convertDOMNode(curChild, scene, curLevel + 1); if((child != NULL) && (child != scene)) { scene->addChild(child); } // now get the child's sibling DOMNode* nextChild = curChild->getNextSibling(); curChild = nextChild; } } } /* else { cout << "<X3DLoader::_convertDOMNode>\tignoring scene without attributes" << endl; scene = new SceneObject(); } */ } else if(domNode->getNodeType() == DOMNode::ATTRIBUTE_NODE) { cout << "<X3DLoader::_convertDOMNode>\tignoring attribute node" << endl; } else if(domNode->getNodeType() == DOMNode::TEXT_NODE) { //cout << "<X3DLoader::_convertDOMNode>\tignoring text node" << endl; return NULL; } } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); cout << "Exception message is [" << message << "]" << endl; XMLString::release(&message); return NULL; } catch (const DOMException& toCatch) { char* message = XMLString::transcode(toCatch.msg); cout << "Exception message is [" << message << "]" << endl; XMLString::release(&message); return NULL; } catch (...) { cout << "Unexpected Exception \n" ; return NULL; } return scene; } SceneObject* X3DLoader::_createSceneObjectFromDOMNode(DOMNode* domNode, bool& parentMustHandleChildren) { assert(domNode != NULL); assert(domNode->getNodeType() == DOMNode::ELEMENT_NODE); // get a usefull version of this node's name char* nodeName = XMLString::transcode(domNode->getNodeName()); // This is the only node we are going to handle for the moment if(strcmp(nodeName, "IndexedFaceSet") == 0) { // parent must ignore children, we can handle them! parentMustHandleChildren = false; return _createMesh(domNode); } else if(strcmp(nodeName, "Transform") == 0) { // parent must ignore children, we can handle them! //parentMustHandleChildren = false; return _createTransform(domNode); } else if(strcmp(nodeName, "Material") == 0) { return _createMaterial(domNode); } /* else { SceneObject* dummy = new SceneObject(); return dummy; } */ return NULL; } SceneObject* X3DLoader::_createMaterial(DOMNode* domNode) { Material* material = new Material(); vector<double> diffuse; vector<double> emission; vector<double> specular; /* <Appearance> <Material +ambientIntensity="0.500" +diffuseColor="0.640 0.640 0.640" +emissiveColor="0.800 0.800 0.800" shininess="0.196" +specularColor="1.000 1.000 1.000" transparency="0.000"/> </Appearance> */ // get the attributes (containing the coord/normal indexes) DOMNamedNodeMap* attributes = domNode->getAttributes(); if(attributes != NULL) { // get the ambientIntensity DOMNode* ambientIntensityNode = attributes->getNamedItem(XMLString::transcode("ambientIntensity")); if(ambientIntensityNode->getNodeValue() != NULL) { cout << "ambientIntensityNode [" << XMLString::transcode(ambientIntensityNode->getNodeValue()) << "]" << endl; } // get the ambientIntensity DOMNode* shininessNode = attributes->getNamedItem(XMLString::transcode("shininess")); if(shininessNode->getNodeValue() != NULL) { cout << "shininessNode [" << XMLString::transcode(shininessNode->getNodeValue()) << "]" << endl; } DOMNode* emissionNode = attributes->getNamedItem(XMLString::transcode("emissiveColor")); if(emissionNode->getNodeValue() != NULL) { cout << "emissionNode [" << XMLString::transcode(emissionNode->getNodeValue()) << "]" << endl; _convertCharToVector(emission, XMLString::transcode(emissionNode->getNodeValue())); } DOMNode* diffuseColorNode = attributes->getNamedItem(XMLString::transcode("diffuseColor")); if(diffuseColorNode->getNodeValue() != NULL) { cout << "diffuseColorNode [" << XMLString::transcode(diffuseColorNode->getNodeValue()) << "]" << endl; _convertCharToVector(diffuse, XMLString::transcode(diffuseColorNode->getNodeValue())); } DOMNode* specularColorNode = attributes->getNamedItem(XMLString::transcode("specularColor")); if(specularColorNode->getNodeValue() != NULL) { cout << "specularColorNode [" << XMLString::transcode(specularColorNode->getNodeValue()) << "]" << endl; _convertCharToVector(specular, XMLString::transcode(specularColorNode->getNodeValue())); } assert(diffuse.size() == 3); assert(emission.size() == 3); assert(specular.size() == 3); material->setAmbient(atof(XMLString::transcode(ambientIntensityNode->getNodeValue()))); material->setShininess(atof(XMLString::transcode(shininessNode->getNodeValue()))); material->setDiffuse(diffuse); material->setEmission(emission); material->setSpecular(specular); } return material; } SceneObject* X3DLoader::_createTransform(DOMNode* domNode) { Transform* transform = new Transform(); Coord3D rotation; double rotationSize = 0; Coord3D translation; Coord3D scale; vector<double> rotationElements; vector<double> translationElements; vector<double> scaleElements; // get the attributes (containing the coord/normal indexes) DOMNamedNodeMap* attributes = domNode->getAttributes(); if(attributes != NULL) { // get the rotation DOMNode* rotationNode = attributes->getNamedItem(XMLString::transcode("rotation")); if(rotationNode->getNodeValue() != NULL) { cout << "rotation [" << XMLString::transcode(rotationNode->getNodeValue()) << "]" << endl; _convertCharToVector(rotationElements, XMLString::transcode(rotationNode->getNodeValue())); } // get the translation DOMNode* translationNode = attributes->getNamedItem(XMLString::transcode("translation")); if(translationNode->getNodeValue() != NULL) { cout << "translation [" << XMLString::transcode(translationNode->getNodeValue()) << "]" << endl; _convertCharToVector(translationElements, XMLString::transcode(translationNode->getNodeValue())); } // get the scale DOMNode* scaleNode = attributes->getNamedItem(XMLString::transcode("scale")); if(scaleNode->getNodeValue() != NULL) { cout << "scale [" << XMLString::transcode(scaleNode->getNodeValue()) << "]" << endl; _convertCharToVector(scaleElements, XMLString::transcode(scaleNode->getNodeValue())); } assert(rotationElements.size() == 4); assert(translationElements.size() == 3); assert(scaleElements.size() == 3); int curIndex = 0; rotation.m_x = rotationElements[curIndex++]; rotation.m_y = rotationElements[curIndex++]; rotation.m_z = rotationElements[curIndex++]; rotationSize = rotationElements[curIndex++]; cout << "rotation size [" << rotationSize << "] x [" << rotation.m_x << "] y [" << rotation.m_y << "] z [" << rotation.m_z << "]" << endl; translation.m_x = translationElements[0]; translation.m_y = translationElements[1]; translation.m_z = translationElements[2]; cout << "translation x [" << translation.m_x << "] y [" << translation.m_y << "] z [" << translation.m_z << "]" << endl; scale.m_x = scaleElements[0]; scale.m_y = scaleElements[1]; scale.m_z = scaleElements[2]; cout << "scale x [" << scale.m_x << "] y [" << scale.m_y << "] z [" << scale.m_z << "]" << endl; } // <Transform rotation="1.000 0.000 0.000 1.571" scale="1.000 1.000 0.603" translation="1.429 -5.224 2.204"> transform->setTranslation(translation); transform->setRotation(rotation, rotationSize); transform->setScale(scale); return transform; } SceneObject* X3DLoader::_createMesh(DOMNode* domNode) { // this is a mesh Mesh* mesh = new Mesh(); vector<int> coordIndexes; vector<int> normalIndexes; vector<double> coords; vector<double> normals; // get the attributes (containing the coord/normal indexes) DOMNamedNodeMap* attributes = domNode->getAttributes(); if(attributes != NULL) { // get the coord indices DOMNode* coordIndexesNode = attributes->getNamedItem(XMLString::transcode("coordIndex")); if(coordIndexesNode->getNodeValue() != NULL) { //cout << "coordIndexes [" << XMLString::transcode(coordIndexesNode->getNodeValue()) << "]" << endl; _convertCharToVector(coordIndexes, XMLString::transcode(coordIndexesNode->getNodeValue())); } // get the normal indices DOMNode* normalIndexesNode = attributes->getNamedItem(XMLString::transcode("normalIndex")); if(normalIndexesNode->getNodeValue() != NULL) { //cout << "normalIndexes [" << XMLString::transcode(normalIndexesNode->getNodeValue()) << "]" << endl; _convertCharToVector(normalIndexes, XMLString::transcode(normalIndexesNode->getNodeValue())); } } // now we need to get the coord/normal objects nodes DOMNode* curChild = domNode->getFirstChild(); while(curChild != NULL) { if(curChild->getNodeType() == DOMNode::ELEMENT_NODE) { cout << "IndexedFaceSet node type [" << domNode->getNodeType() << "] node name [" << XMLString::transcode(domNode->getNodeName()) << "]" << endl; char* childNodeName = XMLString::transcode(curChild->getNodeName()); // get the attributes (containing the coord/normal indexes) DOMNamedNodeMap* curChildAttributes = curChild->getAttributes(); if(curChildAttributes != NULL) { if(strcmp(childNodeName, "Coordinate") == 0) { cout << "<X3DLoader::_createSceneObjectFromDOMNode>\tgot coordinate child" << endl; // get the coord indices DOMNode* coordsNode = curChildAttributes->getNamedItem(XMLString::transcode("point")); if((coordsNode != NULL) && (coordsNode->getNodeValue() != NULL)) { cout << "<X3DLoader::_createSceneObjectFromDOMNode>\tgot point attribute" << endl; _convertCharToVector(coords, XMLString::transcode(coordsNode->getNodeValue())); } } else if(strcmp(childNodeName, "Normal") == 0) { cout << "<X3DLoader::_createSceneObjectFromDOMNode>\tgot normal child" << endl; // get the coord indices DOMNode* normalsNode = curChildAttributes->getNamedItem(XMLString::transcode("vector")); if((normalsNode != NULL) && (normalsNode->getNodeValue() != NULL)) { cout << "<X3DLoader::_createSceneObjectFromDOMNode>\tgot vector attribute" << endl; _convertCharToVector(normals, XMLString::transcode(normalsNode->getNodeValue())); } } } } // now get the child's sibling DOMNode* nextChild = curChild->getNextSibling(); curChild = nextChild; } // now run through the coords and add them to the mesh // *** NOTE *** we make the assumption that there are the same number of normals as vertices // *** NOTE *** we need to presize the mesh vector, because it keeps on copying the polygons vector<int>::size_type normalCount = normalIndexes.size(); vector<double>::size_type coordsSize = coords.size(); vector<double>::size_type normalsSize = normals.size(); int coordIndex = 0; int normalIndex = 0; Coord3D coord; Coord3D normal; Polygon* curPolygon = new Polygon(); for(vector<int>::size_type i = 0; i < normalCount; i++) { //cout << "\tcoordIndex [" << coordIndexes[i] << "] coord x [" << coord.m_x << "] y [" << coord.m_y << "] z [" << coord.m_z << "]" << endl; //cout << "\tnormalIndex [" << normalIndexes[i] << "] normal x [" << normal.m_x << "] y [" << normal.m_y << "] z [" << normal.m_z << "]" << endl; // add to mesh and restart for next polygon // *** NOTE *** we could be reusing the polygon, but I just want to get this going if(coordIndexes[i] == -1) { mesh->addPolygon(*curPolygon); delete(curPolygon); curPolygon = new Polygon(); } else { coordIndex = coordIndexes[i] * 3; normalIndex = normalIndexes[i] * 3; //assert((coordIndex + 2) < coordsSize); //assert((normalIndex + 2) < normalsSize); if(coordIndex + 2 >= coordsSize) { cout << "coordsSize [" << coordsSize << "] coordIndex [" << coordIndex << "]" << endl; break; } if(normalIndex + 2 >= normalsSize) { cout << "normalsSize [" << normalsSize << "] normalIndex [" << normalIndex << "]" << endl; break; } coord.m_x = coords[coordIndex]; coord.m_y = coords[coordIndex + 1]; coord.m_z = coords[coordIndex + 2]; normal.m_x = normals[normalIndex]; normal.m_y = normals[normalIndex + 1]; normal.m_z = normals[normalIndex + 2]; curPolygon->addCoord(coord); curPolygon->addNormal(normal); } } // done, return return mesh; } bool X3DLoader::_convertCharToVector(vector<int>& intVector, string intString) { string piece; //cout << "###############################################" << endl; string::size_type startPos = 0; string::size_type endPos = 0; //int pieceCount = 0; while(endPos != string::npos) { endPos = intString.find(' ', startPos); if(endPos == string::npos) { break; } string::size_type pieceLength = endPos - startPos; piece = intString.substr(startPos, pieceLength); intVector.push_back(atoi(piece.c_str())); //pieceCount++; //cout << "piece [" << piece.c_str() << "] pieceCount [" << pieceCount << "]" << endl; startPos += pieceLength; while((intString[startPos] == ' ') && (startPos != string::npos)) { startPos++; } endPos = startPos; } // now push the last element onto the vector string::size_type pieceLength = intString.size() - 1 - startPos; piece = intString.substr(startPos, pieceLength); intVector.push_back(atoi(piece.c_str())); cout << "<X3DLoader::_convertCharToVector(int)>\tvector size [" << intVector.size() << "]" << endl; return true; } bool X3DLoader::_convertCharToVector(vector<double>& doubleVector, string intString) { string piece; //cout << "###############################################" << endl; string::size_type startPos = 0; string::size_type endPos = 0; //int pieceCount = 0; while(endPos != string::npos) { endPos = intString.find(' ', startPos); if(endPos == string::npos) { break; } string::size_type pieceLength = endPos - startPos; piece = intString.substr(startPos, pieceLength); doubleVector.push_back(atof(piece.c_str())); //pieceCount++; //cout << "piece [" << piece.c_str() << "] pieceCount [" << pieceCount << "]" << endl; startPos += pieceLength; while((intString[startPos] == ' ') && (startPos != string::npos)) { startPos++; } endPos = startPos; } // now push the last element onto the vector string::size_type pieceLength = intString.size() - 1 - startPos; piece = intString.substr(startPos, pieceLength); doubleVector.push_back(atof(piece.c_str())); cout << "<X3DLoader::_convertCharToVector(double)>\tvector size [" << doubleVector.size() << "]" << endl; return true; } /* $Log: x3d_loader.cpp,v $ Revision 1.1 2005/01/28 20:26:58 o3dozone - some refactoring - simple sphere scene object */ --- NEW FILE: x3d_loader.h --- // $Id: x3d_loader.h,v 1.1 2005/01/28 20:26:58 o3dozone Exp $ #ifndef X3D_LOADER_H #define X3D_LOADER_H #include <iostream> #include <xercesc/parsers/XercesDOMParser.hpp> #include <xercesc/dom/DOM.hpp> #include <xercesc/sax/HandlerBase.hpp> #include <xercesc/util/XMLString.hpp> #include <xercesc/util/PlatformUtils.hpp> #include <xercesc/dom/DOMElement.hpp> #include "scene_object.h" #include "model_loader.h" #include "mesh.h" #include "transform.h" #include "material.h" #include <assert.h> #include <vector> XERCES_CPP_NAMESPACE_USE using namespace std; class X3DLoader : public ModelLoader { public: X3DLoader(); virtual SceneObject* loadModel(const string filename); private: SceneObject* _parseX3DFile(const char* filename); SceneObject* _convertDOMNode(DOMNode* domNode, SceneObject* parent = NULL, long curLevel = 0); SceneObject* _createSceneObjectFromDOMNode(DOMNode* domNode, bool& parentMustHandleChildren); SceneObject* _createTransform(DOMNode* domNode); SceneObject* _createMaterial(DOMNode* domNode); SceneObject* _createMesh(DOMNode* domNode); bool _convertCharToVector(vector<int>& intVector, string intString); bool _convertCharToVector(vector<double>& intVector, string intString); }; /* $Log: x3d_loader.h,v $ Revision 1.1 2005/01/28 20:26:58 o3dozone - some refactoring - simple sphere scene object */ #endif --- NEW FILE: simple_sphere.h --- #ifndef SIMPLESPHERE_H #define SIMPLESPHERE_H /* $Id: simple_sphere.h,v 1.1 2005/01/28 20:26:58 o3dozone Exp $ */ #include "scene_object.h" #include <iostream> class SimpleSphere : public SceneObject { public: SimpleSphere(SceneObject* parent = NULL); SimpleSphere(const SimpleSphere& rhs); virtual ~SimpleSphere(); protected: virtual bool _draw(); private: }; /* $Log: simple_sphere.h,v $ Revision 1.1 2005/01/28 20:26:58 o3dozone - some refactoring - simple sphere scene object */ #endif --- NEW FILE: simple_sphere.cpp --- // $Id: simple_sphere.cpp,v 1.1 2005/01/28 20:26:58 o3dozone Exp $ #include "simple_sphere.h" SimpleSphere::SimpleSphere(SceneObject* parent) : SceneObject(parent) { } SimpleSphere::SimpleSphere(const SimpleSphere& rhs) { } SimpleSphere::~SimpleSphere() { } bool SimpleSphere::_draw() { glutSolidSphere(5, 10, 10); //glutWireSphere(GLdouble radius, GLint slices, GLint stacks); drawChildren(); return true; } /* $Log: simple_sphere.cpp,v $ Revision 1.1 2005/01/28 20:26:58 o3dozone - some refactoring - simple sphere scene object */ |